I know the answer (it's 42)

A blog on coding, .NET, .NET Compact Framework and life in general....

Posts
  • I know the answer (it's 42)

    Animation and Text in System tray using C#

    • 13 Comments

    Application running from the system tray is very common these days. Mostly these applications show an icon in the system tray (beside the clock) and almost always have a pop-up context menu.

    Adding additional features like showing text in the tray or show animations is also possible with little code. In this post I have discussed a class I wrote to accomplish this. If you are interested in using this enhanced SysTray class and do not care much about how it works jump to the last section Using SysTray.

    First things first: How do you show an icon in the system tray

    With .NET doing this is pretty simple and there is no need to play around with NOTIFYICONDATA and Shell_NotifyIcon of the Win32 world.

    You just need to create a instance of  System.Windows.Forms.NotifyIcon and fill out the relevant fields as in

    private NotifyIcon m_notifyIcon;

    m_notifyIcon = new NotifyIcon();

    m_notifyIcon.Text = text; // tooltip text show over tray icon

    m_notifyIcon.Visible = true;

    m_notifyIcon.Icon = icon; // icon in the tray

    m_notifyIcon.ContextMenu = menu; // context menu

    That’s it and the icon appear in the system tray and on right clicking on it the menu is popped up.

    Extending the NotifyIcon

    NotifyIcon is sealed so you cannot extend by inheritance. So I created a class SysTray which extends NotifyIcon by creating an instance of it in a field. The constructor takes in the tooltip text, the default Icon and the context menu.

    This class also adds other methods to show animation and text as explained below.

    Showing Text

    An application can only put in an icon in the tray. So the workaround is (there’s always one) to convert the text into an icon. ShowText API of the SysTray class just does this.

    public void ShowText(string text, Font font, Color col)

    {

        Brush brush = new SolidBrush(col);

     

        // Create a bitmap and draw text on it

        Bitmap bitmap = new Bitmap(16, 16);

        Graphics graphics = Graphics.FromImage(bitmap);

        graphics.DrawString(text, m_font, brush, 0, 0);

     

        // Convert the bitmap with text to an Icon

        IntPtr hIcon = bitmap.GetHicon();

        Icon icon = Icon.FromHandle(hIcon);

        m_notifyIcon.Icon = icon;

    }

    What we are doing here is creating a bitmap, drawing the text to be shown on it and then converting it to an icon. Since NotifyIcon can show an Icon in the tray it’ll show the textual icon just fine.

     

    Showing Animation

    Showing animation in the tray is equally easy by making an array of icons each of which represent an animation frame and then switching the icons in the tray on timer events. SysTray accepts the image frame in different formats

    public void SetAnimationClip (Icon [] icons)
    Here icon needs to be an array of 16x16 icon each for a frame


    public void SetAnimationClip (Bitmap [] bitmap)
    Here bitmap needs to be an array of 16x16 bitmap each for a frame

    public void SetAnimationClip (Bitmap bitmapStrip)
    bitmapStrip is a bitmap strip of size n16x16. Where n is the number of frames. SysTray class extracts the individual frames from this strip and converts it to icons and uses it for the animation. 

    The last method is the easiest to use. For this you need to prepare an animation strip image. The image needs to have each frame of animation side by side. Each frame is 16x16 pixels and the color to render transparent is the common background of all the frames. Let’s take

    The caller prepares this image by making it transparent and then calling SetAnimationClip

     

    private void button1_Click(object sender, System.EventArgs e)

    {

        m_sysTray.StopAnimation();

        Bitmap bmp = new Bitmap("tick.bmp");

        // the color from the left bottom pixel will be made transparent

        bmp.MakeTransparent();

        m_sysTray.SetAnimationClip(bmp);

        m_sysTray.StartAnimation(150, 5);

    }

     

    SetAnimationClip uses the following code to create the animation frame

    public void SetAnimationClip (Bitmap bitmapStrip)

    {

        m_animationIcons = new Icon[bitmapStrip.Width / 16];

        for (int i = 0; i < m_animationIcons.Length; i++)

        {

            Rectangle rect = new Rectangle(i*16, 0, 16, 16);

            Bitmap bmp = bitmapStrip.Clone(rect, bitmapStrip.PixelFormat);

            m_animationIcons[i] = Icon.FromHandle(bmp.GetHicon());

        }

    }

     

    To animate the frame StartAnimation starts a timer and in the timer the icons are changed to animate the whole sequence.

     

    public void StartAnimation(int interval, int loopCount)

    {

        if(m_animationIcons == null)

            throw new ApplicationException("Animation clip not set with    

                                            SetAnimationClip");

     

        m_loopCount = loopCount;

        m_timer.Interval = interval;

        m_timer.Start();

    }

     

    private void m_timer_Tick(object sender, EventArgs e)

    {

        if(m_currIndex < m_animationIcons.Length)

        {

            m_notifyIcon.Icon = m_animationIcons[m_currIndex];

            m_currIndex++;

        }

        ....

    }

     

    Using SysTray

     

    This is how you use the class

    1. Create and wire up your menu
          ContextMenu m_menu = new ContextMenu();                                   

          m_menu.MenuItems.Add(0, new MenuItem("Show",new

                               System.EventHandler(Show_Click)));

    2. Get an icon you want to show statically in the tray.

    3. Create a SysTray object with all the required information
          m_sysTray = new SysTray("Right click for context menu",
                      new Icon(GetType(),"TrayIcon.ico"), m_menu);
    4. Create image strips with the animation frames. For 6 frame strip the image will have a width of 6*16 and height as 16 pixels

          Bitmap bmp = new Bitmap("tick.bmp");
          // the color from the left bottom pixel will be made transparent

          bmp.MakeTransparent();
          m_sysTray.SetAnimationClip(bmp);
    5. Start animation indicating how many times you need to loop the animation and the frame delay
          m_sysTray.StartAnimation(150, 5);
    6. To stop animation call
          m_sysTray.StopAnimation();

    Sources - SysTray Implementation: SysTray.cs

     

     

    using System;

    using System.Windows.Forms;

    using System.Drawing;

     

    namespace Abhinaba.SysTray

    {

        /// <summary>

        /// SysTray class that can be used to display animated icons or text in the system tray

        /// </summary>

        public class SysTray : IDisposable

        {

            #region Constructor

            /// <summary>

            /// The constructor

            /// </summary>

            /// <param name="text">The toolip text</param>

            /// <param name="icon">The icon that will be shown by default, can be null</param>

            /// <param name="menu">The context menu to be opened on right clicking on the

            ///                    icon in the tray. This can be null.</param>

            public SysTray(string text, Icon icon, ContextMenu menu)

            {

                m_notifyIcon = new NotifyIcon();

                m_notifyIcon.Text = text; // tooltip text show over tray icon

                m_notifyIcon.Visible = true;

                m_notifyIcon.Icon = icon; // icon in the tray

                m_DefaultIcon = icon;

                m_notifyIcon.ContextMenu = menu; // context menu

                m_font = new Font("Helvetica", 8);

     

                m_timer = new Timer();

                m_timer.Interval = 100;

                m_timer.Tick += new System.EventHandler(this.m_timer_Tick);

     

            }

            #endregion // Constructor

     

            #region Public APIs

            /// <summary>

            /// Shows text instead of icon in the tray

            /// </summary>

            /// <param name="text">The text to be displayed on the tray.

            ///                    Make this only 1 or 2 characters. E.g. "23"</param>

            public void ShowText(string text)

            {

                ShowText(text, m_font, m_col);

            }

            /// <summary>

            /// Shows text instead of icon in the tray

            /// </summary>

            /// <param name="text">Same as above</param>

            /// <param name="col">Color to be used to display the text in the tray</param>

            public void ShowText(string text, Color col)

            {

                ShowText(text, m_font, col);

            }

            /// <summary>

            /// Shows text instead of icon in the tray

            /// </summary>

            /// <param name="text">Same as above</param>

            /// <param name="font">The default color will be used but in user given font</param>

            public void ShowText(string text, Font font)

            {

                ShowText(text, font, m_col);

            }

            /// <summary>

            /// Shows text instead of icon in the tray

            /// </summary>

            /// <param name="text">the text to be displayed</param>

            /// <param name="font">The font to be used</param>

            /// <param name="col">The color to be used</param>

            public void ShowText(string text, Font font, Color col)

            {

                Bitmap bitmap = new Bitmap(16, 16);//, System.Drawing.Imaging.PixelFormat.Max);

     

                Brush brush = new SolidBrush(col);

     

                Graphics graphics = Graphics.FromImage(bitmap);

                graphics.DrawString(text, m_font, brush, 0, 0);

     

                IntPtr hIcon = bitmap.GetHicon();

                Icon icon = Icon.FromHandle(hIcon);

                m_notifyIcon.Icon = icon;

     

            }

     

            /// <summary>

            /// Sets the animation clip that will be displayed in the system tray

            /// </summary>

            /// <param name="icons">The array of icons which forms each frame of the animation

            ///                     This'll work by showing one icon after another in the array.

            ///                     Each of the icons must be 16x16 pixels </param>

            public void SetAnimationClip(Icon[] icons)

            {

                m_animationIcons = icons;

            }

     

            /// <summary>

            /// Sets the animation clip that will be displayed in the system tray

            /// </summary>

            /// <param name="icons">The array of bitmaps which forms each frame of the animation

            ///                     This'll work by showing one bitmap after another in the array.

            ///                     Each of the bitmaps must be 16x16 pixels  </param>

            public void SetAnimationClip(Bitmap[] bitmap)

            {

                m_animationIcons = new Icon[bitmap.Length];

                for (int i = 0; i < bitmap.Length; i++)

                {

                    m_animationIcons[i] = Icon.FromHandle(bitmap[i].GetHicon());

                }

            }

     

            /// <summary>

            /// Sets the animation clip that will be displayed in the system tray

            /// </summary>

            /// <param name="icons">The bitmap strip that contains the frames of animation.

            ///                     This can be created by creating a image of size 16*n by 16 pixels

            ///                     Where n is the number of frames. Then in the first 16x16 pixel put

            ///                     first image and then from 16 to 32 pixel put the second image and so on</param>

            public void SetAnimationClip(Bitmap bitmapStrip)

            {

                m_animationIcons = new Icon[bitmapStrip.Width / 16];

                for (int i = 0; i < m_animationIcons.Length; i++)

                {

                    Rectangle rect = new Rectangle(i * 16, 0, 16, 16);

                    Bitmap bmp = bitmapStrip.Clone(rect, bitmapStrip.PixelFormat);

                    m_animationIcons[i] = Icon.FromHandle(bmp.GetHicon());

                }

            }

     

            /// <summary>

            /// Start showing the animation. This needs to be called after

            /// setting the clip using any of the above methods

            /// </summary>

            /// <param name="loop">whether to loop infinitely or stop after one iteration</param>

            /// <param name="interval">Interval in millisecond in between each frame. Typicall 100</param>

            public void StartAnimation(int interval, int loopCount)

            {

                if (m_animationIcons == null)

                    throw new ApplicationException("Animation clip not set with SetAnimationClip");

     

                m_loopCount = loopCount;

                m_timer.Interval = interval;

                m_timer.Start();

            }

     

            /// <summary>

            /// Stop animation started with StartAnimation with loop = true

            /// </summary>

            public void StopAnimation()

            {

                m_timer.Stop();

            }

            #endregion // Public APIs

     

            #region Dispose

            public void Dispose()

            {

                m_notifyIcon.Dispose();

                if (m_font != null)

                    m_font.Dispose();

            }

            #endregion

     

            #region Event handlers

            private void m_timer_Tick(object sender, EventArgs e)

            {

                if (m_currIndex < m_animationIcons.Length)

                {

                    m_notifyIcon.Icon = m_animationIcons[m_currIndex];

                    m_currIndex++;

                }

                else

                {

                    m_currIndex = 0;

                    if (m_loopCount <= 0)

                    {

                        m_timer.Stop();

                        m_notifyIcon.Icon = m_DefaultIcon;

                    }

                    else

                    {

                        --m_loopCount;

                    }

                }

            }

     

            #endregion // Event handlers

     

            #region private variables

     

            private NotifyIcon m_notifyIcon;

            private Font m_font;

            private Color m_col = Color.Black;

            private Icon[] m_animationIcons;

            private Timer m_timer;

            private int m_currIndex = 0;

            private int m_loopCount = 0;

            private Icon m_DefaultIcon;

     

            #endregion // private variables

        }

    }

     

    Sources - SysTray Usage: Form1.cs

    using System;

    using System.Drawing;

    using System.Collections;

    using System.ComponentModel;

    using System.Windows.Forms;

    using System.Data;

     

  • I know the answer (it's 42)

    Build Type creation and Drop Location

    • 1 Comments

    One of the most common issues everyone is running into with Team Build is configuring the Drop Location.

    All builds that happen through Team Build are dropped (bits are copied) to this location. Drop location is entered in the Location page of the Build Type wizard. This is essentially a shared folder on the network and needs to be available in UNC format as in \\server\share. However most users enter a path in the wizard and then any of the following three things happen

    1.      They forget to share the folder out
    Result: First build fails

    2.      The folder is shared out but adequate permissions are not given on it
    Result: First build fails

    3.      The folder gets unshared at some point of time
    Result: Suddenly builds start failing after that

    A common question is raised that both the first and second reasons of failure are a pre-requisite to starting a build, why doesn’t the Build Type wizard verify that the share exists. We could have done this but there are a couple of reasons we do not.

    Firstly it could be a common scenario that the administrator is first setting up couple of Build Types and will then go and share those folders. So failing would simply hinder this process. However, this is not a very good excuse because we could have at least gone ahead verified the share and then given warnings stating that the share does not exist and the admin should share them with the correct permissions.

    The main reason for not doing this verification is that scenario 2 is not easily verifiable. To undertand this let’s consider the permission required on the shared folder

    1.      The service account under which the Team Build Service is running on the  Build Machine needs write permission on this folder

    2.      Other users need to have read permission on this folder so that they get to see build logs and the build itself

    On the client where the Build Type is getting created through the wizard there is no information regarding the service account on the Build Machine so we cannot verify 1. This is because the admin while installing the BM could have chosen any valid account to run the service and can give explicitly and exclusive write permission to this account on the share. Moreover, user can change the Build Machine while firing the build and the service account on the new Build Machine might be a different account and that might not have permissions.

    On OS’s like WinXP in addition to the sharing permission you can go to the security tab on the folders properties and apply a lot of permissions which are not accessible over the network but would make the build to fail. Take for example in share tab you give Full control to everyone and in the security for that folder you explicitly deny create folder permission. So even though our verification succeeds build will fail.

    Verifying 2 does not add any value if we cannot verify 1.

    Its not that we cannot verify drop location, what I tried to highlight above is that it is non-trivial. Many users think that the Wizard should just try to see if the share exists and then create and delete a file on the share to ensure it is writable. However for the reasons mentioned above this approach would just not work.

     

  • I know the answer (it's 42)

    subscribe / unsubscribe to an event

    • 5 Comments

    In one of the internal aliases there was a discussion going on some time back regarding which is the better way to unsubscribe from an event and why does the first one even work

     

    1. myClass1.MyEvent += new EventHandler(Function);
      Do all stuff
      myClass1.MyEvent -= new EventHandler(Function);

     

    1. EventHandler eventHandler = new EventHandler(Function);
      myClass2.MyEvent += eventHandler;
      myClass2.OnEvent();
      myClass2.MyEvent -= eventHandler;

     

    In the first approach different objects are used to add and remove the event subscription. This can work only if the removal mechanism does not work by just comparing references. Because if it did then the removal mechanism would not find the object in the methods invocation list of the underlying delegate and would simply not remove the method.

     

    I thought I’d do a little more snooping into this.

     

    A class definition like
     public delegate void EventHandler(Object source, EventArgs eventArgs);

        class MyClass

        {

            public event EventHandler MyEvent;

    }

    Is converted to code equivalent to

     

        class MyClass

        {

            private EventHandler __MyEvent;

            public event EventHandler MyEvent

            {

                add

                {

                    lock (this) { __MyEvent += value; }

                }

                remove

                {

                    lock (this) { __MyEvent -= value; }

                }

            }

    }

    So the compiler generates the add/remove accessors.

     

    If you see the code of the accessors in ILDasm then you can see for the add_MyEvent method compiler emits code to call the System.Delegate.Combine method to combine the existing delegate and new delegate and for remove_MyEvent it uses System.Delegate.Remove method.

     

    So

     

    myClass1.MyEvent += new EventHandler(Function); è System.Delegate.Combine (myClass1.__MyEvent, newdelegate)

     

    and

    myClass1.MyEvent -= new EventHandler(Function); è System.Delegate.Remove (myClass1, newdelegate)

     

    So all of the trick lies in the Combine and Remove methods of System.Delegate.

     

    System.Delegate.Remove goes through the invocation list of the first delegate looking for invocations from the second delegate. If there is a match it removes it. System.Delegate overrides the == (Equals) operator so that the match does not happen based on object reference but based on the method the delegate encapsulates. This operator compares the instance object (null in case of static method callback) and the function pointed to and then removes the callback from the invocation list.

     

    So both works but which one should we use? If the events are subscribed/unsubscribed once at the beginning/end like in a typical WinForm application then it hardly matters. However if this is done multiple times then the second approach is preferable as it does less of costly heap allocations and will work faster.

     

    The complete code listing of the sample I used is as follows

     

    using System;

    using System.Collections.Generic;

    using System.Text;

     

    namespace EventAddRemove

    {

        public delegate void EventHandler(Object source, EventArgs eventArgs);

     

        class MyClass

        {

            public event EventHandler MyEvent;


            public void OnEvent()

            {

                if (MyEvent != null)

                    MyEvent(this, EventArgs.Empty);

                else

                    Console.WriteLine("No Event to fire");

            }

        }

       

        class Program

        {

            static void Function(object source, EventArgs eventArgs)

            {

                Console.WriteLine("Event got fired");

            }

     

            static void Main(string[] args)

            {

                Console.WriteLine("myClass1");

                MyClass myClass1 = new MyClass();

                myClass1.MyEvent += new EventHandler(Function);

                myClass1.OnEvent();

     

                myClass1.MyEvent -= new EventHandler(Function);

                myClass1.OnEvent();

     

     

                Console.WriteLine("myClass2");

                EventHandler eventHandler = new EventHandler(Function);

     

                MyClass myClass2 = new MyClass();

                myClass2.MyEvent += eventHandler;

                myClass2.OnEvent();

     

                myClass2.MyEvent -= eventHandler;

                myClass2.OnEvent();

            }

        }

    }

     

    Output is

    myClass1

    Event got fired

    No Event to fire

    myClass2

    Event got fired

    No Event to fire

    Lines in bold indicate that the correct methods was indeed removed from the invocation list in both approaches.

  • I know the answer (it's 42)

    Emails, Emails and more emails

    • 0 Comments

    Just saw the post Slaves to email on excess email in MS and I couldn't agree more.....

    Large email volume for people who manage others, or those who interact with external customers is expected. But even for individual contributors (Dev/Test) the volume is just too high. We should really use the internal communicator more and get rid of those one-liner emails.

    Since we work in a different time zone within a team distributed between Redmond/NorthCarolina/India we face a different issue. Each morning you enter office and you are welcomed with 100s of emails which were sent to you in the local night time. By the time you wade through them almost an hour is over. Mondays are worse as you have to wade through the all the emails sent during Friday in US.

  • I know the answer (it's 42)

    The CLR Nullable DCR works!!!!!

    • 0 Comments

    CLR took a DCR some time back on how nullable types are implemented. See here and here to find out more about the DCR. I found from one of the internal DLs that the fix was already in the RTM bits.

    I wrote a small piece of code which should work only with the DCR changes and kept it aside so once this DCR gets implemented I'd try it out. So each time I upgraded to a new build of VS/CLR I built/ran this code to see if it works. And it just did, with my todays upgrade to about 10 day old build in our lab. The new nullable type after becoming a  basic runtime intrinsic just rocks. I have put in comment all the failures that used to happen previously with the same piece of code....

    // this code works only with the latest bits of
    // Visual Studio 2005 (C#2.0) and will fail to
    // compile/run with older Beta2 bits

    static
    void Main(string[] args)
    {
        int
    ? val = 1;
        int? nullval = null;

        // this always worked
        if (nullval == null
    )
            Console.WriteLine("It worked"
    );

        // this used to fail before and I think one of
        // the biggest issue with the previous implementation
        object
    nullobj = nullval;
        if(nullobj == null
    )
            Console.WriteLine("It worked"
    );

        // previously required 
        // box = Nullable.ToObject<int>(val); argh!!!!
        object
    box = val;

        // If you do not need exceptional code
        // (that's code that throws exception)
        //
     you needed to do int? unbox = Nullable.FromObject<int>(box);
        int? unbox = (int
    ?)box;
        if
    (unbox == val)
            Console.WriteLine("It worked again"
    );

        int intval = (int)box;
        if
    (intval == val.Value)
            Console.WriteLine("attained Nullable Nirvana"
    );

        int x = 10;
        object
    y = x;
        // Previously Exception!!! cast is not valid
        int? z = (int
    ?)y;

        IComparable c = val;
        // Previously Exception!!! : object type cannot be
        // converted to target type
        if
    (c.CompareTo(box) == 0)
            Console.WriteLine("I have seen it all"
    );

        // compilation failure
        IComparable<int
    > ic = val;
        if(ic.CompareTo((int
    )box) == 0)
            Console.WriteLine("Wow there is even more to see"
    );
    }

    The output of the program is

    It worked
    It worked
    It worked again
    attained Nullable Nirvana
    I have seen it all
    Wow there is even more to see

  • I know the answer (it's 42)

    Frame arrangement in image strips used for animation

    • 0 Comments

    Sometimes we get so used to things being the way they are we stop questioning them. We always have the perception in mind that individual frames of animated logo in a Bitmap strip is always horizontally arranged. I remember writing code to extract icons from a image lists that store individual frames of an animation sequence one after the other horizontally using something like

    animationIcons = new Icon[bitmapStrip.Width / 16];
    for (int
    i = 0; i < m_animationIcons.Length; i++)
    {
        Rectangle rect =
    new
    Rectangle(i*16, 0, 16, 16);
        Bitmap bmp = bitmapStrip.Clone(rect, bitmapStrip.PixelFormat);
        animationIcons[i] = Icon.FromHandle(bmp.GetHicon());
    }

    Even winforms ImageList works on this assumption that the AddStrip method of the ImageCollection in the control has the images placed side-by-side. However this is not at all the optimal placement of images. Read it on Raymond Chen's blog .....

  • I know the answer (it's 42)

    CLR takes a DCR for Nullable type

    • 5 Comments

    I saw from Soma's blog that VS is taking a DCR to fix the issues about Nullable types that is being talked about in various blog. This is super cool as Microsoft demonstrated like never before that we do care about customer feedback as this is a direct result of some solid feedbacks. If you do not get the connection read Cyrus Najmabadi blog pointing to one of the original blogs that brought out the issue http://sab39.dev.netreach.com/Blog/12?vobId=172&pm=18

     

  • I know the answer (it's 42)

    Function generator in C++

    • 0 Comments

    Some of us were just chatting about my previous post about function generators and we wondered about whether it can be done in C++ without using function pointers.... Most of my C++ knowledge has been rusted beyond repair but I thought even though its not possible to do directly, one can overload the ( ) operator to simulate this. So it should be possible to code so that the following is valid

    FuncGen(Adder)(p1, p2)

    Here the part in red semantically behaves like a function generator returning different functions based on the flag you pass. So here's some code in C++ that does it. Again I want to stress that this is not a function generator in C++, it just simulates something like it so that a statement like FuncGen(Adder)(p1, p2) will actually work....

    #include <iostream>
    #include
    <string>
    using namespace std;

    enum FuncType
    {
        Adder,
        Subtractor,
        Multiplicator,
    };

    class CFunc
    {
        public
    :
            FuncType m_funcType; 
            template <typename
    T>
            T
    operator
    ()(T p1, T p2)
            {
                if
    (m_funcType == Adder)
                    return
    FuncAdder(p1, p2);
                else if
    (m_funcType == Subtractor)
                    return
    FuncSub(p1, p2);
                else if
    (m_funcType == Multiplicator)
                    return
    FuncMult(p1, p2);
            }

        private:
            template <typename
    T>
            T FuncAdder(T p1, T p2)
            {
                return
    p1 + p2;
            }
            template <typename
    T>
            T FuncSub(T p1, T p2)
            {
                return
    p1 - p2;
            }
           
    template <typename T>
            T FuncMult(T p1, T p2)
            {
                return
    p1 * p2;
            }
    };

    CFunc cfunc;
    CFunc& FuncGen(FuncType ftype)
    {
        cfunc.m_funcType = ftype;
        return
    cfunc;
    };

    int main(int argc, char* argv[])
    {
        int
    p1 = 5, p2 = 1;
        cout << FuncGen(Adder)(p1, p2) << endl;
        cout << FuncGen(Subtractor)(p1, p2) << endl;
        cout << FuncGen(Multiplicator)(p1, p2) << endl;
        return
    0;
    }

    Instead of using a global variable like cfunc I could have also created a object on the heap in FuncGen and later deleted it but since I have been coding in C# so long that I felt too lazy to write a delete statement.

  • I know the answer (it's 42)

    My experiments with continuation in C#

    • 4 Comments

    The blogs are buzzing with continuation support in C# 2.0 and what cool things can be done with it. http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons explains the concept of continuation extremely well. I also found Don Box's posting http://pluralsight.com/blogs/dbox/archive/2005/04/27/7780.aspx very interesting.

    Traditionally in languages like C/C++ functions works off the stack. Each function call creates a new frame on the stack in which current context is stored (return address, current stack pointer) and then any arguments to the function is pushed in. The function also creates all its local variables on the stack and pops them off before the function returns. So when the function returns, all information regarding the functions execution is lost. So in case you call the function again it starts from the beginning.

    However in continuation this is not what happens. Here the state of the function is preserved and when you call back on the function it starts off from where it left off. All the function locals are allocated on the heap so that their values are preserved when the function is called again. In C# we have a *very* restricted version of continuation using the yield return statement. Even though its restrictive it allows some very cool way of programming.

    Here a sample of code where I have a container containing my friends names and I enumerate them.

    public class MyContainer
    {
        string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" };
        public IEnumerator<string> GetEnumerator()
        {
            for (int index = 0; index < m_friends.Length; index++ )
                yield return m_friends[index];
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
           
    MyContainer myContainer = new MyContainer();
            foreach
    (string str in myContainer)
                Console.WriteLine(str);
        }
    }

    You can have multiple enumerators too as in

    public class CoolContainer
    {
        string[] m_friends = { "Samrat", "Kaushik", "Rahul", "Abhinaba" };
        public IEnumerable<string> straight
        {
            get {
                for (int index = 0; index < m_friends.Length; index++ )
                    yield return m_friends[index];
            }
        }
        public IEnumerable<string> Reverse
        {
            get{
                for (int index = m_friends.Length - 1; index >= 0; index--)
                    yield return m_friends[index];
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            CoolContainer cc = new CoolContainer();
        
            foreach
    (string str in cc.Reverse)
                Console.WriteLine(str);
            
           
    Console.WriteLine("----------------");
            
            foreach
    (string str in cc.straight)
                Console.WriteLine(str);
        }
    }

    Seeing all these work I got carried away and tried to do the enumeration without the foreach as in

     

    IEnumerator<string> enumerator = myContainer.GetEnumerator();

     

    enumerator.MoveNext();

    Console.WriteLine(enumerator.Current);

    enumerator.MoveNext();

    Console.WriteLine(enumerator.Current);           

    enumerator.Reset();

               

    enumerator.MoveNext();

    Console.WriteLine(enumerator.Current);

     

    My idea was that after the call to Reset internally I would be able to reach the first element in the list as the index variable will be reset. That’s where I got the surprise in the form of a NotSupportedException in the call to Reset. I send emails to the CSharp user group and found out that its indeed not supported and you need to create new enumerator to go back or if the enumerator once runs till end (i.e. one return is executed) then you’ll automatically get the reset you wanted. This means that iterating twice or more using the same iterator works as in

     

    MyContainer myContainer = new MyContainer();
    foreach
    (string str in myContainer)
        Console.WriteLine(str);
    foreach (string str in myContainer)

        Console.WriteLine(str);

  • I know the answer (it's 42)

    Team Build notification tool

    • 11 Comments

    < this tool has been updated check out here>

    As we go on developing the product we frequently feel strong about doing new things around our product either to increase customer value, easy of use, flexibility or just because it can be done. Most of these are either too late to be included in the product or does not meet the criteria. Either way they serve as great samples and keep us busy.screen shot of build ticker

    One great example would be RSS feed for Team Foundation version control checkin notifications. Check out http://blogs.msdn.com/jefflu/archive/2005/07/27/443900.aspx. So now in addition to getting emails, you can also subscribe for RSS feeds.

    Similarly for Team Build I have written a tool that monitors Team Build events and shows notifications with link to the Web UI of the Build. Currently it has the following feature

    • The tool can monitor any number of Team Foundation servers and is not tied to a single server.
    • It works over web services and does not need any VS installation to run. So this can be installed on your home PC to monitor if the build you fired before leaving office succedded or failed.
    • It has links to the Web UI, so you can also open the detailed report in the browser and see the status.
    • Poling frequency can be changed at two levels. Polling for list of builds from server and polling individual builds.
    • It shows cool Office 2003 like notification over the system tray and also animated icons in the tray.

    I plan to add additional features like listing all builds on the server and allowing user to specify different user name to connect to the server (required if running from home PC).

  • I know the answer (it's 42)

    Anonymous methods and closures in C#

    • 8 Comments

    Anonymous Method

    One of the new features in C#2.0 being shipped in with Whidbey is anonymous methods. Though this at first glance looks like an easy way of creating delegates, where instead of having to create a new function which the delegate will call you can pass the code inline.

    Before C#2.0

    class MyClass
    {
         delegate void MyDelegate
    ();
         static public void
    Function()
         {
             Console.WriteLine("I'm called"
    );
         }

         static void Main()
         {
            MyDelegate writeMessage = new MyDelegate
    (Function);
            writeMessage();
         }
    }

    With C#2.0 and anonymous methods: the Function is eliminated and the same piece of code can be written more elegantly as follows

    class MyClass
    {
        delegate void MyDelegate();
        static void Main()
        {
            MyDelegate writeMessage = delegate ()
                                      {
                                          Console.WriteLine("I'm called"
    );
                                      };
            writeMessage(); 
        }
    }

    For more details on Anonymous methods check out http://msdn.microsoft.com/msdnmag/issues/04/05/c20/default.aspx.

    However, there is more to it than just getting a short hand way of writing code. With anonymous methods you can now do a lot of things in C# which are commonly done in Functional languages. Consider the code below which is actually a function generator.

    class Program
    {
        delegate void MyDelegate
    <T>(T t);
        enum
    FunctionType
        {
            WithPrefix,
            WithoutPrefix
        }
        static MyDelegate<T> FunctionGenerator<T>(FunctionType
    fType)
        {
           
    int i = 0;

            if (fType == FunctionType
    .WithPrefix)
            {
               
    return delegate(T t)
                       {
                           Console.WriteLine(i.ToString() + ": "
    + t.ToString());
                           i++;

                       };
            }
            else
            {
                return delegate
    (T t)
                       {
                           Console.WriteLine(
    t.ToString());
                       };
            }
        }

        static void Main(string[] args)
        {
            MyDelegate<int> mdWith = FunctionGenerator<int>(FunctionType
    .WithPrefix);
            mdWith(5);
            mdWith(5);

            MyDelegate<string> mdWithout = FunctionGenerator<string>(FunctionType
    .WithoutPrefix);
            mdWithout(
    "Hello"
    );
        }
    }

    The output is
    0 : 5
    1 : 5
    Hello

    As in the above piece of code you can create Function Generator that actually return different implementations based on requirement. For another interesting sample see Don Box's blog http://pluralsight.com/blogs/dbox/archive/2005/04/17/7467.aspx

    Closure

    For any languages which allow passing around functions as arguments or functions returning another function the Closure abstraction is very important. For more info on Closure see http://en.wikipedia.org/wiki/Closure_(computer_science). C#2.0 supports closure by the use of anonymous methods.

    Closure is a function along with its lexical environment (available variables and their values) when the function is created.

    int i = 10; 
    return delegate(T t)
    {
        Console.WriteLine(i.ToString() + ": "
    + t.ToString());
    };
     

    Since the variable i was available with the value 0 when the Anonymous method was created, inside the method, i will be available with the same value when the method is called via the delegate.

    From the definition of Closure it can be inferred that Closure remembers the values of the variables during its creation. However in C# the outer local variable (i in this case) is shared with the anonymous method by creating it on the heap. This means any change to it in the anonymous method changes the original value and when the method is called the second time it gets the modified value of i as 1 (see second line of output). This leads many to argue that anonymous method is not actually a Closure as by its definition the value of a variable at the time of creation of the Closure should be remembered and not modifiable.

    Check out the link http://blogs.msdn.com/brada/archive/2004/08/03/207164.aspx on how the implementation of Anonymous methods in C# have led to interesting issues.

  • I know the answer (it's 42)

    Renaming, Deleting or Hiding a Build Type

    • 3 Comments

    Renaming, deleting or hiding a build type is not directly available from the Team Explorer or from any menu or tool bar. Essentially a Build Type's name is same as the name of the sub folder in which the build type files are checked in. So if there is a team project MyTeamProject with a Build Type MyBuildType this means there is a source control folder on the server with the server path

    $/MyTeamProject/TeamBuildTypes/MyBuildType

    On Beta 2 bits the path will be $/MyTeamProject/TeamBuildConfigurations/MyBuildType

    So renaming means renaming the folder named MyBuildType. Deleting would mean deleting this folder. If you want to hide this Build Type from coming up in the Team Explorer you need to rename the file TeamBuild.proj inside this folder to some other name ($/MyTeamProject/TeamBuildTypes/MyBuildType/TeamBuild.proj). The steps are as follows

    Adding Workspace Mapping

    Edit workspace dialog First you need to have a workspace that maps the TeamBuildTypes folder (or TeamBuildConfiguration on Beta2 bits). To do this go through the menu File -> SourceControl -> Workspaces... Select a workspace and click edit and then add the mapping similar to the one shown in the screen shot. Rest is more easily done from the command prompt.

    Open a Visual Studio 2005 command prompt. In that cd into the local folder that maps the TeamBuildTypes folder. Run the following command to get the latest files
    tf get * /r.

    Hiding a Build Type

    cd into the MyBuildType folder and run the following
    tf rename TeamBuild.proj foo.proj
    tf checkin

    This should bring up the checkin window. Click on the Checkin button. Now if you refresh the Team Explorer the build type should go away from under the Team Build node.

    Rename Build Type

    To rename the BuildType go to the folder above and run the following 
    tf rename MyBuildType CoolBuildType
    tf checkin

    On refreshing the Team Explorer a new Build Type named CoolBuildType should come.

    Deleting a Build Type

    To deleting a build type run
    tf delete MyBuildType
    tf checkin

     


     

  • I know the answer (it's 42)

    TechEd Hyderabad starts tomorrow

    • 0 Comments
    TechEd is starting tomorrow in Hyderabad (home to the MS India development centre). Most of the devs in our team will not be able to attend tomorrow and we will join the show from Tuesday. VSTS is getting a lot of attention this year and we heard great stories from the people who attended TechED in Bangalore and Chennai. The India Team System team working on Team Build and the converters will all be there in our Black T-shirts with Team System written in front. So if any one of you have any questions or need any insider info ;) catch us.
  • I know the answer (it's 42)

    marking required fields on forms/UI

    • 3 Comments

    How do you communicate to users which fields on a UI is required and which is optional? This was the questions I was trying to answer while implmenting the Team Build Type creation wizard. Though there exists some common conventions in Web forms like marking the fields with asterix and putting something like "Fields marked with an asterix * are required" somewhere on top, there seems to exist no convention to do this on Windows user interfaces.

    In team system the work item tracking UI does this by making the background color of the required fields  with the same color as tooltip (yellow) and then as soon as the user types in some thing in them the color changes back to window backgorund color (white). So the user can quckly review the form and can locate fields that are left to be filled as they are marked with a different color (yellow).

    I liked this idea a lot and wanted to do the same thing with our wizard and Start build forms. But could'nt get that approved by the User Experience team becuase they think that on wizards the visual cue should come from the enabling of the Next button. The idea is that once the user has filled in all the required fields in the page Next should get enabled so that he can move to the next page. I think this works well only when the number of controls on the Wizard page is less, other wise the user will keep trying to guess why the next button in not getting enabled. Since wizard guideline clearly calls out against crowding too many things in one page, I guess this is fine but still think we should move towards a common guideline on marking required fields and I think the background color change is a fine way of doing just that.

  • I know the answer (it's 42)

    What are the Build Types, how do I edit them

    • 9 Comments

    For people new to Team Build do read Overview of Team Build

    Though most people using Team Build easily finds out how to create a build type and fire a Team Build, they find it difficult to figure out how to edit a Build Type. So one of the common use scenario is to re-create the Build Type again with the changes required. Though this is perfectly fine and talks a great deal about the ease of using the Wizard to create a new build type, but results in Build Types hanging around.

    Editing build type is easy once you know what is a Build Type and where they go once created.

    How do you create a Build type

    Right click on the Team Build node on the Team Explorer and choose "New Team Build Type" from the context menu. This launches the Wizard to create the Build Type (refer Using the New Build Type Wizard for more info)

    Where did the Build Type go?

    Once a Build Type is created a set of three files are created and checked in to source control at the following server location $/{TeamProjectName}/TeamBuildTypes/{BuildTypeName}

    In Beta2 the server location used to be $/{TeamProjectName}/TeamBuildConfigurations/{BuildTypeName}. So replace all references to TeamBuildTypes with TeamBuildConfigurations if you are working with VS2005 Beta2

    Team Build operates and works on some thing called Build Types. Build Type is essentially a set of 3 files that reside on the Source Control as follows

    • $/{TeamProjectName}/TeamBuildTypes/{BuildTypeName}/TeamBuild.proj
      The main BuildType file that we would be interesting is editing.
    • $/{TeamProjectName}/TeamBuildTypes/{BuildTypeName}/VCOverrides.vsprops
      Used for building VC++ projects to override some build properties like the OutputDirectory
    • $/{TeamProjectName}/TeamBuildTypes/{BuildTypeName}/WorkspaceMapping.xml
      This is used to recreate the users Workspace on the Build Machine to sync sources prior to build.

    Interestingly the Build Type name is not stored in any of the files. The name is same as the name of the folder in TeamBuildTypes that contain these files

    Viewing the Build Type files

    Build Types in Source Control Viewing the build type files is same as viewing any file in the Source Control. You need to create a Workspace that maps the Build Type files to some local folder, sync the file and open them in any text editor. This can be done in a number of ways and one of them is clearly mentioned as comment on top of the generated TeamBuild.proj file. So if you right click on any of the Build Types under the Team Build node in the Team Explorer and choose "View Team Build Type" then the file is downloaded from the server to the local machine and opened in VS. One thing to keep in mind is that the file opened is a local copy and changes made to it will NOT be reflected in the actual TeamBuild.proj on the server.

    Editing the file

    Double click on the version control node in the Team Explorer to bring up the Source Control Explorer. If in the Folder list the TeamBuildTypes and its children are grayed out then that means that the folders are not mapped in the current workspace. In the tool window on the top of the Source Control Explorer select Workspaces... in the Workspace drop down. Select your current workspace and click on edit. In the Edit workspace dialog add mapping for the TeamBuildTypes folder. See image.

    Edit workspace dialog

    Once the mapping has been added right click on the TeamBuildTypes node in the folder and get the latest version. After that right click on the TeamBuild.proj and check out for edit. Double click on the file to open it in VS for edit.

    TeamBuild.proj file is an xml file and heavily commented so that it is easy to edit. Just look for <Description> and add some description to the Build Type, search for <DropLocation> and change the location where the build bits will be dropped. Keep reading the comments and that will guide you in your changes to this file. At the end save the file and go back to the Source Control Explorer, right click on the checked out TeamBuild.proj and check in the file and you are done

    You can verify that your changes have gone through by right clicking on the Build Type you changed in the Team Explorer and choose "View Team Build Type". The opened Build Type should have your changes in it.

     

     

     

     

     

  • I know the answer (it's 42)

    Using the New Build Type Wizard

    • 8 Comments

    Team Build and Build Types

    The build type wizard is used to generate Build Types which are a collection of Build Scripts used to fire the remote builds on the Build Machines. These scripts are XML scripts consumed by MSBuild which is used by Team Build to build the user's solutions. Just as the local VS build works on solutions (.sln) and projects (.proj) Team Build works on Build Types.

    Entry Point

    You need to have the Team Explorer open (View->Team Explorer). There is couple of entry points in Visual Studio to the New Build Type Wizard. It can be launched by right-clicking on the Team Build node in the Team Explorer (under any Team Project) or through the menu Build->New Team Build Type. The later works only when a solution is open in VS (cause the top level Build menu comes up only when a solution is currently open).

    Using the Wizard

    There are six pages in the Wizard. Only when all the mandatory fields are filled in a page the next button gets enabled. The Finish button remains disabled till you reach the end of the Wizard. You can also browse between the pages using the navigation pane on the left. If the links of some of the pages are disabled on the pane this means that some of the pages have to be filled before reaching that page.

    In case you get a pop-up saying that "No workspace Exists for the Given team project". It means that there is no source control workspace on the client that maps into the Team Project. Change an existing workspace mapping or create a new workspace for the team project for which you are trying to create the build type.

    Welcome page

    You need to give a name to the Build Type. This is the only mandatory field on this page. Build Type name has to be unique for the Team Project.

    The Wizard verifies the uniqueness of the name when you hit Next and gives an popup error message in case is finds another Build Type with the same name.

    Selections Page

    This is where you select the solutions you want to build for the Build Type. The combo box on top shows the names of the available workspaces with the name of the workspace owner in parenthesis. Select the workspace and all the solutions in the source control that are mapped in the workspace will be listed. Check all the solutions you want to build and use the arrow buttons on the right to set the order in which the solutions will be built. The ordering may be important if there are interdependencies between the solutions and one solution requires the binaries generated by another solution.

    If you do not see any solutions listed, it means that there are either no solutions checked in to the source control or the workspace mapping is not correct.

    Configurations Page

    You can give the configurations that will be built for each of the solutions. This is the same list that you see in through Build->ConfigurationManager. You can add as many unique combinations of Configurations and platforms you need. The platform list is pre-defined and can be any one of x86, x64, Itanium, Win32 and AnyCPU. Configuration can be Debug, Release or any other user defined configuration.

    The solution should support the given combination i.e. you must have had added the same configuration/platform pair in Build->Configuration Manager for that solution for the build to succeed.

    Location Page

    This is where you specify which build machine will be used and where the built binaries will be dropped (copied to). Type the name of the Build Machine (server name) without the leading \\.

    The build directory is the local folder on the build machine where the sources are downloaded from the Team Foundation Server and built using MSBuild. This folder is created in case it is not already present. You have to give the local path of the build directory on the build machine (something like c:\builds). In case you are wondering why there is no browse button beside the folder name the reason is that the folder is a local folder on the build machine and will not be browsable from the client machine where you are creating the Build Type. This is more of a internal detail that has been exposed. For all normal purposes you will not be needed to be bothered about the build folder.

    Both the build machine and the build directory can be overridden at the time of firing the build.

    The drop location is the place where the binaries will be copied to once the build is over. You need to create a folder on a server and share it out with write permission to Everyone and then type the name here. This needs to be in UNC format (\\server\share). You can browse for the share on the network. In case you forget to share out the folder with write permission then build will fail.

    In case you fail to browse for the drop location try browsing to the same machine using "My network places"->"Entire Network" in Windows explorer. Most probably you'll see the same error as the one you saw in the Wizard. Call your network admin to fix issues with your permission settings or any other network issues.

    Build Steps

    Though this page is named Build Steps you can only change the test related steps through this page. Check the Run Test checkbox if you have a test project in your solution and would like to run the tests in it once the solutions are built. The test metadata file and test list become mandatory fields if the run tests check box is checked. All the vsmdi files in the Team Project will be listed here. Select the once you want to use to test. The test list combo box will be automatically updated to show all the test lists in the vsmdi file. You can choose any one of the test list or use the default "All loaded tests".

    If no vsmdi files show up in the combo box then there are no such files checked into source control. You will be needed to create test projects check them in to source control and try creating the Build Type again.

    Check the perform code analysis check box if you want to run FxCop for static analysis of the source code.

    Summary Page

    Finally this is where the Finish button gets enabled. Review the selections you had made in all the pages, pray to god and hit the Finish button

    What happens next?

    Team Build generates the build scripts and some associated helper files and checks them in. If the Build Type name in MyBuildType then this is what is created and checked into source control

    $/MyTeamProject/TeamBuildConfigurations/MyBuildType/TeamBuild.proj This is the main build script file that is generated by team build $/MyTeamProject/TeamBuildConfigurations/MyBuildType/CustomAction.targets This file is included by TeamBuild.proj and is used for customizing team build to suit your organizations

    A node named MyBuildType is created under the Team Builds node in the Team Explorer and the created TeamBuild.proj file is downloaded to a temporary file and opened in Visual Studio. Note that this is a temporary copy and changes made to it are not reflected on the server. I will post some time later on how to modify the teambuild.proj file.

    Firing a Build

    Right-click on the newly created node (MyBuildType) and then in the context menu choose "Build Team Project <MYTEAMPROJECT>". In the dialog that opens click on the Build button. If all is well, build should start and the Build Summary page should come up. Double click on the name of the build just fired and see the detailed report.

    In Beta 2 the summary and the detailed report does not auto refresh. So you need to manually refresh the pages using the refresh button on top of the Summary page or the context menu of the detailed report page. When the build complets click on the drop location link on the detailed report and the folder with the binaries just built will come up.

  • I know the answer (it's 42)

    Visit to redmond

    • 0 Comments

    Its almost a month, I'm here in Remond. I was very excited to come to the heart of things where everything of VSTS other than team build gets done. I was very excited to meet all the people and attach faces to the email aliases and caught off handed many a times when someone looked or talked so differentlly than the person you conjured in your mind. I loved the open campus which is so different than the walled campuses I have seen back home.

    I was surprised to see a soccer field in the middle of the campus. I always thougt that cricket and soccer is not so common in US. A visit to the cafeteria and a stroll around was enough to explain it. There are so many europeans and latin americans all around. I met people from so many coutries, people from Vietnam, Russian, England, China, Japan and of course from India. Did not see Bill Gates yet, but I do hope to catch a glimpse of him.What I hated most about the place was the rains. Do not get me wrong here, I am from coastal country and love the rains. But back home rain is torrential like a white blanket that comes down and cleans the earth of dust, dirt and sin. Then the sun is back again and you run for shelter. Here the rain is like a dripping tap, it goes on and on like drip, drip, drip, drip, drip.....

    I visited Whidbey island and took a photo of an insect on a leaf. Then had a blast sending an email to all the folks in India that I found a bug in Whidbey and sent a link to the picture. I gave the bug repro steps as well. Visit Whidbey, look around on the leaves and you'll find plenty of bugs.

  • I know the answer (it's 42)

    Team Build blog

    • 2 Comments

    I guess the least represented module of Visual Studio Team System on msdn blog was Team Build . This is going to change now with the Team Build PM khushboo taking up bloging actively. See http://blogs.msdn.com/team_foundation or http://blogs.msdn.com/team_foundation/archive/2005/03/02/383479.aspx

     

  • I know the answer (it's 42)

    command line tool syntax

    • 1 Comments
    Command line interface (CUI) designs for many of the tools found with VS or in Windows were to include a bunch of individual commands or exe with options or flags.

    To get a directory listing: dir <options> as in dir c:\temp /w
    To create a directory: md c:\temp\foo
    To delete a directory: rd /s c:\temp\foo

    So even though all the tasks pertain to directory or path handling , you need to know three command to do the task. This design is slowly changing to the format of command <action> [</options:attributes>]

    For example if we change the above commands to this format with the common command called dir, we will be getting
    To get a directory listing: DIR list c:\temp /w
    To create a directory: DIR  make c:\temp\foo
    To delete a directory: DIR rem c:\temp\foo /s

    So effectively user learning is reduced. One can argue that he still needs to remember the names of the actions. But in the previous case he needs to remember rd, md, dir. Now he knows everything to do with path handling is to be done with DIR. So he can run DIR /? to get the list of actions and then do a DIR list /? to know the options for listing. The other advantage is namespace pollution in terms of the names of the executables also reduces.

    This new format has also been adopted in the VS as in the source control tool. So to get the listing of all workspaces on MyServer you  run the command
    h.exe workspaces /s:MyServer
    To create a new workspace you run the command
    h.exe workspace /new MySpace /s:abhinab-test
    I guess going forward we will see more and more of the standard OS commands also taking up this format. A very common example is the NET command

  • I know the answer (it's 42)

    Error messages

    • 2 Comments

    Frequently we are presented with error message pop-ups with messages like "Unable to open file". Error messages are popped up when something has gone wrong. If SW cannot convey to the user what went wrong and what he can try to fix the problem, it might as well not show the error message at all.

    So all errors messages must have three components

    • Notification
    • Explanation
    • Solution

    A good example for a Team Build scenario would be

    Unable to connect to the build machine "BuildServer01"
    Make sure that the machine is connected to the network and the TeamBuild Service is running on it.

    So all error messages that have one sentence in them are most probably not as helpful as it states what happened and not what can be done to rectify it.

    Another important thing to note is that the user is never to be blamed for any error. If the action he did was dumb then we are at fault that we did not restrict him from committing a dumb action.

  • I know the answer (it's 42)

    TSunami and tribes getting extinct

    • 3 Comments

    Two days have gone by and the TSunami death toll is rising. Its already 12500 in India with thousands more missing. The state of Andhra Pradesh where the Microsoft India center is based is also one of the worst hit states with hundreds of people dead along the coastal region of the state. MS has also joined into the relief operation by giving funds and matching employee contributions.

    On another note one of the worst hit areas of India the Andaman and Nicobar islands are also home to some of the rarest tribes on our planet. With the most isolated community on earth the Sentinelese living here. Many of the tribes living in remote islands have only 100 in population and might have gone extinct after this natural disaster. Government is yet to reach these islands and find out. Sentinelese and Jarawa community also does not establish contact with any outsiders and no one knows what has happened to them.

    You can read more in http://timesofindia.indiatimes.com/articleshow/973963.cms

     

  • I know the answer (it's 42)

    All new MSN blog

    • 1 Comments

    With all those blog servers floating around I was waiting for MS to do something about it, and voila there are here with http://spaces.msn.com . Its free provides all that other blog servers do and more. MS has made it a habit to wait and watch a technology to grow and mature, then take it up and make it reach new heights :)

    Just thought I'll copy/paste the feature list I got through an internal mail

    MSN Spaces Enables Rich Self-Expression

    MSN Spaces enables consumers to easily share things with the people they care about in a format that can be easily customized. People can start a Space with just a few clicks, and then personalize it to reflect their moods, likes and dislikes:

    ·         Rich layout. Fifteen custom backgrounds and five layout template choices allow consumers to customize their MSN Spaces quickly.

    ·         Web logs. The MSN Spaces blogging tool allows people to publish and maintain online personal journals and enables them to link to photos and other Web sites.

    ·         Photo albums. Consumers can upload up to 10 MB of photos (250 images after compression) to their Spaces sites and display them to others in slide shows.

    ·         E-mail uploads. Consumers can upload photos or blog postings to their Spaces from virtually any e-mail service or e-mail-enabled mobile device.

    ·         Music favorites and lists. Consumers can create and manage lists of information that is important to them, such as their favorite music, books or travel destinations. Consumers can easily share playlists through their Space with Microsoft® Windows Media® technologies. With just two clicks, people can sample or purchase a song on someone’s playlist through MSN Music.*

     

    MSN Spaces Helps Users Connect With Others

    MSN Spaces is designed to help people express themselves online while better connecting them with their friends, family and other contacts:

    • Contact Cards. When a person clicks on a Contact Card in a MSN Messenger or Hotmail® Contact list, the card pops up and gives a sneak peek at that contact’s Space – from its look and feel to the person’s most recent postings. The Contact Card includes links to the Space and those entries for easy access.
    • Gleaming. When a Spaces site is updated or content is added, the MSN Messenger Contact icon of the Space’s owner will light up, making it easy for friends and family to know when there have been changes. This facilitates more visits to a Space, faster responses to new postings and closer bonds between Space owners and their contacts.
    • RSS. MSN Spaces also supports RSS 2.0, so consumers can publish their Space to others by way of RSS viewers and aggregators, including My MSN, scheduled to come soon. This is another way to ensure that the people who matter to a user can stay up to date on his or her Space.

     

    MSN Spaces Offers Protection and Control

    MSN Spaces is designed to give consumers control over how they share their Space information and who can access it:

    • Permissions. Consumers have three permission control settings on their MSN Spaces site, enabling them to decide just how widely they want to share their content:

             Public: Viewable by anyone

             Contacts Only: Viewable only by their MSN Messenger contacts

             Private: Viewable only by contacts whose e-mail addresses are manually entered by the MSN Spaces author or selected from an MSN Contact list

    • Controls. MSN Spaces gives the consumer control over how others interact with his or her Space. MSN Spaces includes settings that give each person power over who views his or her Space and how people can interact, read and comment on the Space. This includes the ability to set up the Space so people can read but not comment.
    • Statistics. Consumers will be able to track visitor statistics on their Spaces site, so they will know how many people are visiting as well as other detailed information
  • I know the answer (it's 42)

    software piracy in India

    • 28 Comments

    I always tried to figure out that in spite of the fact that India will become one of the largest PC markets in the future and that India SW engineers are everywhere, why is there no mainstream software in Indian languages. Yea there is Windows Hindi, and I read somewhere that Windows Bengali is also coming up, but thats after years of existance of Windows in other not so prevalent languages. I always got the answer that this is mainly due to SW piracy. Its so prevalent here that almost no one pays for software and hence the SW companies do not have revenue motive to localize their software for India. A further study revealed that 63% of al PCs in India ship with pirated Windows!!!! A person who is ready to use a pirated OS, will surely not pay for any other software he installs on that box. So this can lead to millions of dollars lost in revenue for the SW companies.

     

    Its so bad here that frankly till date I have rarely seen a home user using a legitimate copy of Windows. Even when I have seen that, it was in branded PCs which came pre-installed with the OS. The moment I congratulated someone for using a legitimate OS, within a minute he figures out that he was made to pay for the OS by the PC vendor, and he felt bad that he could have got the pc for less if he had a way for not opting for the OS.

     

    This issue is not only with home users, its every where, its in cyber cafe's, in SOHO, even in mid size organization and colleges. PC vendors are adding fuel to fire by shipping PCs with Linux pre-inslalled on them. This serves as a simple solution to buy a branded PC at a lower cost. People buy this PC, goes home and installs Windows from pirated CDs which cost them around Rs.100, thats a little more than $2. So now you have a branded PC running Windows sans the price.

     

    Many have suggested that low cost software is a solution to this. I absolutely do not agree with this. It may be a part of a solution but not the solution in itself. SW piracy has become so prevalent that no one feels like paying for it. You are considered a fool if you pay. What is required is a change in the way of thinking, user education and pride of ownership. People need to know that its equivalent to stealing, and is a punishable offense. This is a bad thought though, with 63% of all PCs shipping with pirated OS, it brings most my friends and relatives who own a PC in this category...

  • I know the answer (it's 42)

    Steve Ballmer visiting India

    • 0 Comments

    The CEO of Microsoft Corporation, Steve Balmer is visiting Hyderabad on the 15th (next Monday). There's a lot of excitement around this. He is supposed to inaugurate a part of the new Microsoft Campus and also to lay foundation stone for the second phase.

     

    Hyderabad is very proud to house the MS IDC, a race it won by defeating several other cities. This visit is raising lot of rumors and some sites have gone as far as to predict that the new center will slowly grow and employ 5000 developers and will be the largest outside US.  Check out http://economictimes.indiatimes.com/articleshow/915404.cms. This appears to be a very distant reality. Personally I’m eager to hear what he has to say.

     

    MS was working out of rented facilities that spread across multiple floors in different buildings. Since these building are part of Software Parks, some additional benefits come with it. You get banks, ATMs, florists, travel agents, restaurants all at the same place.

     

    However, like most people I prefer the company having its own campus. You get a feel of unity and get to meet a lot more people from your own company. Casual chats over a cup of coffee can give amazing insight into a different technology domain which the other guy sharing your table works in. I just can’t wait to get into the new building once it start functioning…

  • Page 15 of 15 (374 items) «1112131415