Steven's profileDevelopmentalBlogLists Tools Help

Blog


    October 14

    Visual Studio Tooling, Resharper, and the Developer Circle of Life

    Visual Studio is pretty good. 2008 came a long way and I really enjoyed jumping to it with some production apps with the beta 2 release. But I also had those same thoughts about VS2005, and to be honest, VS2003 was a god-send after VS2002. I guess the point is that when something is new, such as an IDE or a language, you start to learn all the little tricks, and they’re all great. Productivity is enhanced, you discover new ways of doing things, and you hit this little peak for the year where you really enjoy what you do.

    Invariably that peak levels off as the new and interesting becomes the common place. You start looking forward to the NEXT release and the productivity gains it will bring. I call this the ‘Developer Circle of Life’. We are invariably bound to it and cannot escape. Whatever we have now, we want it faster, with new features, and some new technologies to boot.

    Its those middle months that suck the most, the longing, wishing you were using V.Next on your current project, and that everything is so hard and slow. So what can you do until that beta 2 ‘go live’ license to improve your developer experience? Where can you get more productivity gains? Well there’s a suite of plugins and tools you can install that work integrated or in parallel with Visual Studio out there. One of the most common is Resharper, and I’d like to share some of its qualities with you.

    Resharper

    Ok so I used to be that guy that wanted everything vanilla. Default options all the way. It allowed me to move between client sites easily and be completely operational immediately. When I hit a computer with Resharper, I’d immediately know because VS would start closing my brackets and quotations for me automatically; that was the hallmark of R#, and I would immediately disable it. But in the last year I’ve been really focusing on doing WPF work (I’m even launching a new WPF blog – coming soon) and found the VS2008 XAML editor to be loathsome. I mean, it just seems to be notepad with syntax highlighting and a little bit of intellisense – that’s it. Others around me were using R# so I bit the bullet and installed the trial.

    Ok I got used to the closing brackets/quotation thing quickly. Even VS will close XML elements and quoted attributes for you. I got over that issue pretty quick and to be honest, I could only find two other griefs with it (I’ll mention them below) – otherwise there wasn’t much else to complain about.

    But the benefits? Wow.

    There’s so many things that you just keep discovering all the time, but there is definitely a few standouts that I use all the time. Here’s 5 of my favourites:

    1. XML Namespacing

    In XAML editor, you get a lot of improvements around refactoring but the feature I enjoy the most is the auto-discovery of namespaces. Lets say you have a control that you created and you want to declare it in XAML. In plain old VS (hereto referred to as POVS) you first have to find your namespace with the intellisense in the Window element at the top of your editor, declare the namespace prefix, then come back down to where you want your control, and instantiate it. With R#, you can just declare <myControls:SpecialControl /> and press the R# magic key combo of ALT+ENTER and walla! It discovers where SpecialControl is within your application and inserts the namespace automatically, and even calls it ‘myControls’ for you. This is a very quick operation that makes it easy to get your XAML bashed out faster, but also for the absent minded like me, means I don’t have to remember the namespace for my controls!

    2. Convert Property to Backing Fields

    You’re probably familiar with code snippets in POVS. In VS2005 I used the ‘prop’ snippet all the time; this created a public property with a private field backing it. However when VS2008 came out, they replaced this snippet with a new one that created an ‘automatic property’ instead. Automatic properties are extremely short and concise already, so its beyond me why the VS team would not leave the original prop declaration as is. R# to the rescue! You can quickly create an automatic property, and then using ALT-ENTER convert it to a property with a backing field. Given I do so much WPF (and love the MVVM pattern), I tend to need properties with backing fields all the time (for my little friend INotifyPropertyChanged). I love this feature. Oh, and it converts back to an automatic property as well if you don’t like it.

    3. Go To Implementation

    Or CTRL-F12. I also use a lot of IOC which means interfaces hiding my implementations a lot of the time. Also its a services world, and WCF patterns see interfaces for contracts as well. POVS had the F12 ability – go to definition, which bounced your cursor to wherever the item you clicked on was declared. BUT if this was an interface, well you got dumped at the interface. Fear not! R# lets you go to the actual implementation of your interface instead. You can actually count the time this saves in a day in terms of minutes I reckon. Oh and if more than one class implements the interface, it gives you a list to choose from of course!

    4. CTRL-T

    I’m sure this has a proper name, but I just call it “THE GREEN BUTTON” since it is such an enabler. Basically, need to know where something is? CTRL-T will find it. Its the enhanced search aspect of R# but its killer feature is that you can type in the letters of your class based on its pascal case definition, and it will be returned as a search result. I know that crappy description really does describe it correctly, so I’ll use an example. Lets say you have a class called ‘VolumeIntegrationProvider’ (which I do) – you can press CTRL-T and type “VIP” and it will find that class! So you see what I mean about the pascal case?

    5. Initialise Field From Parameter

    Another thing about IOC is that you inject a lot of classes into your constructors. Its then a manual task to create a private field within your class to store that parameter, and of course the code in the constructor to assign it:

    private IVolumeIntegrationProvider _volumeIntegrationProvider;
    public MyClass(IVolumeIntegrationProvider volumeIntegrationProvider)
    {
        _volumeIntegrationProvider = volumeIntegrationProvider;
    }

    This really is time consuming, but with R#, you only need to declare the constructor parameter and ALT-ENTER takes care of the rest! This is another one of those features that saves you minutes a day (hmm, there seems to be a few of them!).

    Dislikes

    The first is that sometimes the R# intellisense/autocompletion is not fast enough for me. Somehow I just know that a class name is unique after the first 4 characters (perhaps I’ve just typed it 3 times before) and so I’ll bash out the keys really quickly. For example, imagine I wanted to type this:

    if (_volumeIntegrationProvider is IVolumeIntegrationProvider) …

    So I’d type the following characters: 
    i f SPACE ( _ V o CTRL-SPACE SPACE i s SPACE I V o CTRL-SPACE ) ENTER

    (CTRL-SPACE is auto-completion, so it should fill in the remainding characters for that class/interface)
    Generally I’ll bash out those key commands so quick that Resharper can’t react in time, and the result is a complete mess on my screen. This takes time to mend. Subsequently I’ve become tuned to slowing down on auto-completion.

    The only other dislike I have is that R# leaves your VS in a bit of a mess when you uninstall it, the worst part being that your intellisense and other features might actually be disabled. However this is pretty rare and really isn’t such a big deal.

    All I can say is that you have to give R# a try. Install the trial and see how you go. I bet that after the trial expires you’ll be forking out the measley few USD it takes to get it going again. =)

    Other Tools

    As a user of TFS, I quite like the TFS Power Tools. This provides some must-have extensions to the command line configuration of TFS, as well as shell integration for your source control. I also usually install the VS2008 Power Tools which gives you some useful functions like being able to copy-paste your assembly references. I used to think RockScroll was cool, but lately I think it just steals too much screen real-estate and it doesn’t deal with collapsed code very well.

    Its not very 3rd party but when it comes to dealing with the designer aspect of XAML (building UI that looks good) I actually prefer to use Expression Blend, and I’ve even taken the leap into Expression Design lately to build some of my assets and icons. I’m really enjoying those products but am also suffering some of those random crashes people have been complaining about. Even still, Blend 3 is awesome and sometimes I just sit in there and bash out ideas for fun.

    May 24

    WPF ListViewItem – Stretch to take the full width

    I’m doing a bit of WPF at the moment for a company in Sydney and also working on a WPF project in my spare time. Tonight I came across this issue and thought I’d document the simple solution in case I run into it again in the future.

    I have a ListView that takes up the full width of my window. I’ve edited the ListViewItem template to put a border around the items. The code looked like this:

    <ListView BorderThickness="0">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                                <Border Margin="10" Padding="8" BorderBrush="Red" Background="GhostWhite" CornerRadius="12">
                                              ……. my content here ….
                                </Border>
                        </DataTemplate>
                    </ListView.ItemTemplate>
    </ListView>

    The problem was that the border was only as big as the content inside it, even though the listview was the width of the window. What I wanted was to show an equal sized border for each item despite the size of the content inside.

    The solution in the end was really quite simple: to add the HorizontalContentAlignment="Stretch" attribute to the ListView declaration. Easy!

    March 24

    Ada Lovelace Day 2009 – Catherine Eibner

    Ada Lovelace Day is an international day of blogging to draw attention to women excelling in technology.”

    From: http://findingada.com/

    I only heard about this today to be honest. Perhaps that makes me part of the problem, I’m not sure. I don’t want to go into the gory details of equality in the workplace. What I do want to say is that there is definitely a clear lack of female role models in the industry. That’s why this pledge is so important: there are a lot of women out there doing excellent things in the community and that’s why I’m writing this post: my pledge to talk about a woman in the industry that I admire: Catherine Eibner.

    Catherine is one of the most community focused people I have ever met, male or female. A single mother who also started her own company, while kicking off the Sydney CRM user group, a podcaster and geek girl,  a regular attendee of Sydney user groups in general and frequent speaker herself, Australia wide.

    Catherine was awarded the MVP status from Microsoft, only to have it recalled when she became a Microsoft full-time employee for the DPE group: just two more indicators of how much the community appreciates her involvement.

    Whenever I am in Sydney and looking for the local community events, Catherine is always there to show me the way! Thankyou Catherine, and keep up your good work. The world’s a better place for having you.

    You can find Catherine here:

    I encourage all of you to post about a female in the tech industry you admire and why. If you don’t know one, at least spend the time to think about why that might be.

    February 27

    A Fractal Generator in C# for .Net 3.5

    Fractals are interesting creatures. They are the visual representation of complex mathematical functions. Writing a fractal generator was something I always wanted to do, and recently found the time. My initial motivation was to discover if fractals were able to be generated using parallel processing, which they most certainly are, so I set off with a clear goal in mind: a multi-threaded fractal generator. This post is the result of that work.

    I’ll start by linking to Snagy.Fractals.zip. This zip file contains 3 projects: a core fractal library, a console app, and a WPF app. The 2 apps use the fractal library to generate fractals in both single and multi-threaded scenarios.

    Mandelbrot

    One of the most common functions is the set of numbers defined by Benoit Mandelbrot in the Mandelbrot Set. This function relates to the concept of Complex Numbers and the plotting of co-ordinates on the Complex Plane. This particular branch of mathematics is complex and I’m not going to talk about it here (mostly because I still don’t know how it all works!). Suffice to say that the fractals generated from the Mandelbrot set are the most common and well documented. I selected the Mandelbrot algorithm for my fractal generator.

    Existing Generators

    Before I started this work I thought it more worth while to use an existing generator if one was available. There were some, but one of the key problems I discovered was that they were badly written and difficult to understand. Having said that, some might find the same problems with mine, and if that is the case, please let me know!

    Another problem I discovered was that some of these generators were written by mathematicians. This meant that the language and terminology used presumed an understanding of the maths (which I only have part of) and that made the code difficult to read. So my goal was to lose the jargon and stick to programming terms.

    Snagy.Fractals

    After spending some time on the mathematics, I followed some online guides to programming the fractal, as well as munging in some concepts from some example applications I found. Snagy.Fractals namespace is the end result, and here is an overview of the important classes within.

    FractalSettings – Contains just properties representing the required settings for a fractal
    MandelbrotBase – An abstract class that provides helpers for settings, timing, and pixel creation
    MandelbrotSingleThreaded – A derived class that creates fractals in a single thread
    MandelbrotMultiThreaded – A derived class that creates fractals in multiple threads
    Fractory – A factory class for generating the derived class based on settings
    ColourMap – Static class that creates arrays of colours used in the fractal

    How It Works

    This won’t be a math lecture so we’ll just cover some simple concepts. First, fractals are generated on a pixel by pixel basis. This makes them excellent candidates for parallelism: 2 pixels can be generated at the same time because there is no relationship between pixels.

    The work we do is broken up into ‘Strips’. Imagine we want a fractal that is 900x900 pixels in size. We can break this up into 200x900 strips, with the 5th strip only being 100x900 pixels. These strips allow us to break our work up into logical units. These strips are what get distributed amongst multiple threads.

    Scale

    Think about a 900x900 fractal image again. If we just run the standard co-ordinates through the functions (x = 1 to 900, y = 1 to 900) then the Mandelbrot fractal is quite small (a couple pixels). This doesn’t let us see anything interesting! So we need to simulate “zoom”. To do this we take a scale modifier and multiple the numbers against that. The best top level zoom starts at scale 0.01. This means we are supplying the algorithm with the numbers x = 0.01 to 9.00 and y = 0.01 to 9.00. But the most amazing art occurs much deeper still!

    Offsets

    Because Mandelbrot is based on quadratic equations (eg. y = ax^2 + bx + c ) then everything happens around the ‘Origin’. This means we need to introduce negative X and Y values, with the centre of our image being co-ordinate 0:0. To achieve this we need to offset calculations based on how big our image is (Height/2, Width/2) and also based on our zoom level. This moves the fractal to the centre of our screen (in this case, the centre of our bitmap that we are creating).

    Centre

    When we start zooming in, we don’t actually want to look at the exact centre of the image. If you look at pictures of Mandelbrot, you’ll see the very centre is empty! Nothing exciting happening there, so we actually need to zoom in at specific x/y locations. These locations have to take into account the offsets mentioned above, and of course the scale factor.

    Iterations

    The colour of any pixel is decided by the number of iterations of the Mandelbrot function that can occur. What we mean by this is that the function : f(n) can be called on itself recursively “i” number of times while satisfying the core equation (see complex quadratic equations for details). So if the deepest we can go at a particular point is f(f(f(f(f(n))))) then this means we reached 5 iterations.

    Forget the math though; the MandelbrotBase class will calculate the iteration for you based on the x/y co-ordinate. However this x/y co-ordinate is actually relative to the centre mentioned above, so is in fact quite a small number pair, rather than the actual X/Y of the bitmap we are calculating.

    To Infinity – And Beyond!

    If you zoom in on an ‘edge’ of a fractal, you will see that you can keep zooming.. forever and ever. Well this isn’t technically true: the app is hardcoded to 1000 iterations max, which means that there are defined edges between the fractal and space. But theoretically.. .there is no such edge!

    Snagy.Fractals.Console

    All the fractal work is done in the class library, so its really very easy to consume and use in your own application. The console application is a perfect example of this. All the code in this app is around getting command line parameters and turning them into a FractalSettings instance, and then saving the resulting fractal image. Use this application as a guide to using the fractal classes.

    Snagy.Fractals.WPF

    This is a simple harness that will show you the fractal based on your settings on the left. Enter a scale and centre point, then click create.

    I did attempt to put some navigation into it, but its very flaky. There is this tendency for UI events to “queue” while the fractal is being generated. As a result the experience is rather poor, but the framework is there if someone wants to work on it and make it work better.

    Summary

    This is open to anyone to use. Since its unusual to embed a fractal generator in a commercial app, I’m not too concerned about what you use it for. But if you do republish an app with my code, I’d appreciate a mention and a link through. =)

    Thanks

    I have to thank Buddhike for his help around the threading. Bud helped me get the locking sorted along with the right threading classes. So thanks Bud! I’d also like to thank Paul Stovell for making me ditch my original Win Forms harness and use WPF instead, which resulted in more work to convert bitmaps, recreate my flashy UX, and fight against dispatchers.

    The WPF navigation (pan and zoom) was based on this article on the topic.

    Technorati Tags: ,,,
    January 30

    TFS Shared Resources in Mesh

    I was lucky enough to get an early invite to Live Mesh (I was working at Microsoft at the time). Back then it seemed more like a concept than an implementation there were that many flaws. I tried it for a while, but fell back to folder share and other technologies. Mesh got uninstalled.

    To be honest, I hadn’t looked at Mesh since that time. Until today.

    It all started as the result of a TFS engagement I had just finished consulting on down at the Gold Coast. I decided to build a TFS Resource Pack for all the common files you typically need on a TFS engagement. For example, VSTS SP1, TFS 08 SP1, SQL Server 2005 SP1, TFS sync tool, TFS migration tool, Branching Guidance document, TF Power Tools, Team System Web Access SP1, the list goes on!

    Usually I just download these tools on site at the client but I figured it would be easier to have a portable HDD with all these items (I don’t own such a HDD but was willing to buy one). I ran the list of items in my pack past some internal Readify guys and one of the responses was: ‘Why not mesh?’

    Why not indeed! There’s 5Gb worth of space in the cloud that I can use so why not put all these resources in one place where I can always get them? Maybe not the 1Gb ISO’s for service packs, but certainly the rest can go there.

    So as of today, there is a folder in mesh with all this information, and I plan on continuing to add to it over time.

    Want access? All you need is a Live Mesh account and send me your email: I’ll invite you to the folder so you can get the files as well (read access only if I don’t know you). And then just email me if you think I should add any particular file or application.

    Technorati Tags: ,,
    January 24

    The Right Administrator Permissions in TFS, WSS, and RS

    I tend to forget the right permissions to set for TFS 2008 and its various components. And not all the various permissions are readily searchable on the net. So this quick blog entry is just a reminder for myself.

    Create Projects in TFS

    To create a project in TFS you need the relevant TFS permission ‘Create new projects’ which is defined at the server level. By default, the ‘[SERVER] Team Foundation Administrators’ group has this permission, but being a member of this group is just not enough. When you create a new team project, TFS also creates a new site in Windows Sharepoint Services (WSS), and a new folder in Reporting Services (RS). So it only makes sense that the user should have permissions to be able to perform both those operations as well.

    Reporting Services is pretty easy. With your admin account that installed TFS (TFSSetup perhaps?) go to your Reporting Services web folder, typically it is something like this: http://tfsrtm08/Reports. You will be able to see the sub folders for each of your projects, but we need to set permissions at this root level. Click on the ‘Properties’ tab and click ‘New Role Assignment’. Specify your user account (or AD group) and tick all the boxes. Finally click OK and you are done. RS permissions are inherited so the user will get access to all sub folders, now and in the future.

    WSS is a bit more interesting. Adding a user to the root site and giving them ‘Full Control’ in fact does nothing. It is not like RS where the permissions are inherited. Full Control on the root site means ONLY the root site, not sub sites, and not the ability to create new sub sites. What you need is the ‘Site Collection Administrators’ permission for the root site instead. Find it by going ‘Site Actions –> Site Settings –> Site Collection Administrators’. Add your user here and they will be able to create sub sites. However it is worth noting that this does not entitle your user to full control over all sites that are created: it will only give them full access to the ones that THEY create. If someone else creates one, this user will NOT have access. We’ll deal with this below.

    Full Admin Privileges

    One of the things I find is that TFS management (including permissions) falls to the hands of the infrastructure team. And infrastructure guys like to manage permissions through Active Directory. They like to have a ‘TFS Admins’ group in AD and for anyone to have full access, they want to be able to just add them to that group and not have to think about it any further. It makes sense somewhat because this is how a lot of their user maintenance occurs in their day-to-day jobs.

    As mentioned earlier, just because you have Site Collection Administrator privileges does not mean you have full control over all sub sites. If you create a new site, you will be given admin access to that site. But if someone else creates one, then you will NOT have access. Site Collection Admin only lets you create sites, nothing more. So normally you have to add users to a site after it is created. But sometimes there is a lead developer or sys admin who should have full access over all WSS sites, regardless of who created them. This permission is a little harder to find.

    To fix this, you need to access WSS Central Administration, which is typically something like http://tfsrtm08:17012/. You will need to do this with your TFSSetup account (or equivalent) since it will be the only account out of the box that has WSS Central Admin privileges. Go to: ‘Application Management –> Policy for Web Application’ and click ‘Add Users’. On the first screen, ensure Zones is set to ‘All Zones’ and click Next. Then under ‘Choose Users’ add your user account to the box and click the little ‘tick’ icon below to ‘check names’. Check the box for ‘Full Control’ and click ‘Finish’.

    This gives your user full access over the whole application, which means all future sub sites that may get created.

    Summary

    I’m not really sure what best practice is, but from my experience it is often best that only the TFSSetup account has master access to everything. Creating a new team project is not something that should happen every day. It represents something big, a new era of development. Its something that will have a lifecycle, iterations, management and buy-in from stakeholders inside and outside your development team. It makes sense that there should be one person responsible for the project and relevant RS and WSS site. This should be the person who gives out additional privileges for developers and managers to those additional components.

    Still, the customer is always right. =)

    Technorati Tags: ,,,,
    January 20

    CreateFoldersItem Custom Task for MSBuild

    Last year I did a fair amount of MSBuild stuff, and really enjoyed it. And when I recently wrote an MSBuild task to clean up TFS source bindings in Visual Studio solutions and projects, it rekindled my interest and reminded me how much I like MSBuild.

    That’s why today I decided to write another task to add to my library. I wanted to be able to get an item group containing folders, in particular the last name token each directory. For example, for the path “C:\Program Files\BitLocker\en-US\” I wanted to get the “en-US”.

    I did a quick look to see if there was a way to do it with the existing ‘CreateItem’ task, or if anyone else had tried to do this and had a solution. But to be honest I didn’t look TOO hard because I really wanted to tackle this problem myself!

    Enter: Snagy.Tasks.CreateFoldersItem

    I’m actually writing this post while I work on the task. Think of it as a step by step account, and I’ll be writing in a present tense, so forgive me if it sounds daft. But if you’ve never created a custom task for MSBuild before, I’ll cover off all the basics.

    First, I created a class library project in C# (actually I already had one from the last task I wrote, so I am just adding to that). Up front you’ll want to add some assemblies to your references list:

    Microsoft.Build.Utilities
    Microsoft.Build.Framework

    Next, add a new class, call it ‘CreateFoldersItem’. At the top, add using statements for the 2 above namespaces, and add a using statement for System.IO while you are at it. Now, make your class inherit from ‘Task’ which is in the Microsoft.Build.Utilities namespace. You can also choose to implement ITask instead, but then you need to provide a little more information in your class. Its easier just to inherit from Task instead. One final thing you need to do to make it build is override the ‘Execute’ method. Do this now but don’t provide any implementation yet other than to ‘return true’. Build your task to make sure its all hunky dory.

    Next we want to provide attributes on our task that people can use to set information to be used by the task. I was thinking of a syntax something like this:

    <CreateFoldersItem Include=”C:\Projects;C:\Program Files”                    
                                  Exclude=”C:\Projects\MSBuild\;C:\Projects\Lisp”
                                  Recursive=”true”>
         <Output ItemName=”AllFolders” TaskParameter=”Include” />
    </CreateFoldersItem>

    This would take semi-colon delimited folders as input and provide a single ItemGroup of all sub-folders. If Recursive is false, only look 1 level deep, otherwise hit the bottom. The Exclude is a little tricky but I think just a semi-colon delimited list of folder names will suffice. Also I’ve deliberately used a semi-colon delimited list for Include and Exclude so that we can use ItemGroups as inputs in both those cases. That way you could use this task to create an include list and an exclude list, and then create a third list which is a delta of the two.

    Ok so back to our class. We need to define 3 properties here. For my task, only the ‘Include’ attribute is mandatory. Exclude will be empty by default, and Recursive will be false by default. We can easily create the properties with C#3.0 syntax:

    [Required] [Output] public ITaskItem[] Include { get; set; }
    public bool Recursive { get; set; }
    public ITaskItem[] Exclude { get; set; }

    The ‘Required’ attribute means the Task cannot be called without mention of that property. And the ‘Output’ attribute means that the property can be used in the ‘TaskParameter’ attribute of the <Output> element. The ITaskItem interface stores individual items for passing around. It is best practise to use an array of these for accepting and returning ItemGroups.

    Now we need to focus on our core functionality. We need to iterate through each Include item and add each sub-folder to a list. Since each include item might be a child or parent of another include item, we need to think about duplication. Until now I hadn’t thought if I want my returned ItemGroup to include duplicates. This could easily be configurable for the user by adding a ‘bool Distinct’ property but I’ll just assume that we don’t want duplicates to make it easy.

    One of the things I want to be able to do is get some metadata out of my returned folders, specifically the last location in the folder path token (the ‘en-us’ in the example earlier). I’ll call this the folder ‘Name’ (since this is the convention used by the DirecoryInfo class in System.IO). This lets us get just the folder name using metadata like this:

    <Message Text=”Folder name = %(AllFolders.Name)” />

    Let’s start by creating a simple method that takes the string path of a folder and returns an ITaskItem which includes the above described metadata:

    private TaskItem CreateTaskItemFromFolder(string folder)
    {
        DirectoryInfo di = new DirectoryInfo(folder);
        Hashtable metadata = new Hashtable();
        metadata.Add("Name", di.Name);
        return new TaskItem(folder, metadata);
    }

    So what’s happening here? Well we use the DirectoryInfo class to provide us the last token in the directory path, via the ‘Name’ property (ie. di.Name). Metadata needs to be added via a non-generic implementation of IDictionary, in this case I used a System.Collections.Hashtable. The best implementation of an ITaskItem is the TaskItem class (surprised?) and its constructor lets us provide the folder path and the metadata as parameters.

    Now we can use this method to create a TaskItem for each folder that we find. We need a method that will accept a base folder as a parameter, and return a List of TaskItems based on all child folders (with consideration to the ‘Recursive’ option). Here’s a method that does just that:

            public IList<TaskItem> GetChildFolders(string folder, bool recursive)
            {
                SearchOption searchOption = (recursive ?
                                             SearchOption.AllDirectories :
                                             SearchOption.TopDirectoryOnly);
                string[] subfolders = Directory.GetDirectories(folder, "*", searchOption);           
                IEnumerable<TaskItem> children =
                      subfolders.Select(s => CreateTaskItemFromFolder(s));
                return children.ToList();
            }

    We utilise the existing ‘GetDirectories’ static method of the System.IO.Directory class. This method has an overload that accepts the ‘SearchOption’ enum which pretty much means recursive or not. Note that when specifying SearchOption.AllDirectories, the search will recursively search your whole tree from that point, even following folder shortcuts. This means if you have a shortcut to a higher level folder, you could potentially get stuck in an infinite loop. So be careful: if this task is called with Recursive=true, then ensure its not called on a folder that nests to itself via shortcuts.

    Finally with a little bit of lambda magic, we create a task item from each folder returned by GetDirectories. That’s all the hard work done, we just need to bring it together in our Execute method and overwrite the ‘Include’ folder with the new results. Here’s what the first bit of code in our Execute method looks like:

    IList<TaskItem> results = new List<TaskItem>();

              foreach (ITaskItem item in Include)
              {               
                    IList<TaskItem> children = GetChildFolders(item.ItemSpec, Recursive);
                    results = results.Union(children).ToList();
              }

    Essentially the above code just creates one big list of task items by unioning the result of each folder call. After the loop completes we have all the included subfolders in one list. We now need to remove any exclude folders from that list. The next bit of code looks like this:

                foreach (ITaskItem item in Exclude)
                {
                     results = results.Where(x => x.ItemSpec.ToLower() != item.ItemSpec.ToLower()).ToList();
                }

    This code is not as difficult as it looks. Once again we use a lambda to specify a condition on which we want to filter results. That condition is based on matching the folder strings from the exclude list against those in the current results list. The output is a new list without the matching items, and we just overwrite Results with this new list.

    The last piece of the puzzle is to push our output back into the Include list of task items:

    var r = results.Cast<ITaskItem>();
    Include = r.ToArray();

    Simply put, we need to cast our list of TaskItem to a list of ITaskItem and then push it out as an array.

    And that’s it! A couple things to mention though. In the final version of my code there are lots of checks around whether folders exist. Its also worth mentioning that instead of using .Select and .Where methods, you can use standard LINQ syntax instead. I just found the lambda syntax more concise and easier to read.

    So what’s the final result? Well you can do funky things like this:

    <CreateFoldersItem Include="C:\Projects\Secret"
                                  Recursive="true"
                                  Exclude="C:\Projects\Secret\NotReallySecret">
                 <Output ItemName="SecretFolders" TaskParameter="Include" />
    </CreateFoldersItem>
    <CreateFoldersItem Include="C:\Projects"
                                  Recursive="true"
                                  Exclude="@(SecretFolders)">
                 <Output ItemName="AllFolders" TaskParameter="Include" />
    </CreateFoldersItem>

    In the above example, we get an item group for all folders under C:\Projects except for all the secret projects. Note that AllFolders will include C:\Projects\Secret\NotReallySecret\ because it was excluded from the first list!

    I hope you find this task useful. You can download the DLL and example usage here.

    January 11

    Remove Source Control Bindings - Visual Studio 2008

    Ever find yourself giving code to someone else? Maybe its an official handover of the source, or perhaps an example to post on your blog. Well, if you keep your solution in Team Foundation Server and it is bound to source control, then the solution will contain information about its TFS bindings. If you've ever attempted to open a solution with such bindings, but are unable to contact TFS, you get a series of popups indicating that TFS couldn't be found, would you like to work offline, etc. This is certainly not something you want other people to have to put up with when you give them your solutions, its just bad form!

    It is quite easy to remove these bindings in Visual Studio. You can unbind via 'File -> Source Control -> Change Source Control' and this works just fine. Your solution and project files will have the relevant source control sections removed, and the extra files (.vssscc and .vspscc) will be deleted.

    But what if you want to automate this process?

    Unfortunately there are not a lot of options around. Deleting the files is pretty easy; create an item group for the two extensions above, and call the delete task on them. But what about modifying solution and project files? This has prompted people to come up with their own solutions, one such as from John Robbins who created an MSBuild task for removing these bindings. Unfortunately John's task did not work for me and I presume this is because he targets Visual Studio 2005, not 2008 (the article was written in 2006). This gave me the fuel to come up with my own solution instead.

    Download Snagy.Tasks.dll

    The above download will give you the DLL and an example MSBuild file to use. There are essentially 2 tasks that do two separate things.

    RemoveTFSBindings

    This task removes bindings from SLN and CSPROJ files. I have no immediate plans to add support for VBPROJ or DBPROJ but if you really want these included, I am happy to do so. Just email me.

    This task is called like this:

    <RemoveTFSBindings SourceFile="Src.sln" TargetFile="New.sln" />

    Yes, it only processes one file at a time, however it is quite easy to call it with an item group as follows:

    <ItemGroup><ProjectFiles Include="$(path)\**\*.sln;$(path)\**\*.csproj" /> </ItemGroup>
    <Target ...>
      <RemoveTFSBindings SourceFile="%(ProjectFiles.Identity)" ReplaceTarget="true" />
    </Target>

    The above example will replace each file with a version of the file without source bindings.

    RemoveSCCBindingFiles

    This task removes all dedicated source control files in a given folder, with the option of repeating the process recursively. It is called like this:

    <RemoveSCCBindingFiles Folder="$(path)" Recursive="true" />

    It targets and deletes all .vssscc and .vspscc files.

    Usage

    Not sure how to use a custom task? All you need to do is import each task with the 'UsingTask' task, like this:

    <UsingTask TaskName="Snagy.Tasks.RemoveTFSBindings" AssemblyFile=".\Snagy.Tasks.dll" />
    <UsingTask TaskName="Snagy.Tasks.RemoveSCCBindingFiles" AssemblyFile=".\Snagy.Tasks.dll" />

    Disclaimer

    I've tested the tasks on a variety of projects created by different people and it seems to work fine. That being said, I'm standing by the "It works on my machine" motto. I can't guarantee it will work for you. Please note that my tests have been specifically around TFS and doubt that this will work for any other source control binding.

    Also, I included an EXE version as well just in case you wanted a different avenue of usage. I only did this though because Paul Stovell begged and pleaded for it. Its included in the download link above.

    Good luck!

    January 07

    TFS: After a rename, I can’t get a specific changeset!

    This post deals with the intricacies of Source Control in Team Foundation Server. A common operation is to do a ‘Rename’, particularly on a folder. So how does this affect the changesets for all files in that folder?

    MoneyMaker

    For this post, assume I have a product called ‘MoneyMaker’ in my TFS Project:

    image1    image2

    We are halfway through release 1.2.7 however the company has just come up with a new naming standard! We decide to check-in our last change to the service contract for safety, it was pretty much done anyway. It becomes changeset: 10081.

    image3

    Ok so now we have to perform a rename of the folder to match our new versioning strategy. The company wants to use letters instead of numbers for its convention. So the new version will be: A.B.G.

    image4 image5

    Ok so the rename was a success. Even the local folder has been updated. But I just realised I made a mistake with my last checking before the rename! I want to get an earlier version of that service contract. So let’s see what happens when I use the “get specific version” option on the file and specify the first changeset 10080.

    image6  image7

    Well, the ‘get’ seemed to do something, but we now have something funny happening:

    image8

    For some reason, the file now has a status of “Not Downloaded”. The file has even disappeared from the local file system:

    image9

    So what gives? Well believe it or not, this is completely by design. Think for a moment about that changeset 10080, the first changeset for the file. It existed when the folder name still reflected the old versioning strategy (v1.2.7). So that version of the file at that point in time belonged to a v1.2.7 folder, not a A.B.G folder. So Team Explorer did the right thing: it deleted the current copy, then went to download any relevant files for that folder (A.B.G), of which there were none. So what happens when we try to get that changeset from a level higher than renamed folder?

    image10 image11

    Well the ‘get’ happens as usual, but takes a little longer since it now has more files to process. But something interesting has now happened: the folder name has reverted back to the original! And the local file system reflects the same information:

    image14  image15

    Now you can get to the old versions of your files prior to the rename. But this is still a bit of a pain so be mindful of your renames. Have a think about the checkboxes in the ‘get specific version’ dialog to ensure that your ‘get’ doesn’t take all day.

    January 06

    Object Finalization : IDisposable, Dispose(), Destructors and Garbage Collection

    I apologise for the long title, but I wanted to be clear about what this post will cover. I was recently updating some of Readify’s courseware and was looking at our Garbage Collection section; that prompted this post.

    Concepts

    First lets define 2 concepts: Dispose() method and the Finalizer. In C#, the Finalizer is known as the ‘Destructor’ and is a special method that follows this syntax:

    public class MyClass {
       public MyClass() { ..constructor logic.. }
       ~MyClass() { ..destructor logic.. }
    }

    As you can see, a destructor follows the constructor logic, but has a tilda ~ in front. In VB.Net there is no equivalent, however you can override the Object.Finalize method instead (which incidentally you can’t do in C#). So that is essentially the direct equivalent. Incidentally, because every class inherits from object, your class already has a Finalizer, it just doesn’t do anything until you implement it yourself.

    Dispose() is a method that you define. There is an interface called IDisposable which will force you to implement this method. If you don’t define it, your class doesn’t have it.

    What Are They Used For

    Both the Finalizer and the Dispose() method are used for cleaning up your objects. This might be closing database connections, letting go of a disk file, or closing a stream from your serial port. It also means releasing handles to unmanaged resources such as pointers and COM artefacts.

    The Finalizer (destructor) is called when the garbage collector cleans up your object. But garbage collectors are unpredictable: they will clean up your object whenever they feel like it. This is known as ‘non-deterministic finalization’ because we can’t determine when the object will be cleaned up. Also, the destructor is not a proper method so you cannot call it from your code.

    The Dispose() method is just that: a method that you can call whenever you like. This makes it ‘deterministic’ in that we can determine when the cleanup will occur: when we call the method. By implementing IDisposable we are also telling other artefacts that we have that special cleanup method and can be called. A good example of that is the “using” statement. Here is an example:

    using (StreamReader sr = new StreamReader(“C:\test.txt”)) {
      string s = sr.ReadToEnd();
    }

    In the above example a StreamReader object is created and utilised. The ‘using’ statement ensures that the Dispose() method is called at the closing bracket. In fact, it will do this even if an exception occurs within the ‘using’ scope. However, you can only use this syntax on classes that implement IDisposable.

    Which Do I Use

    If you have nothing to cleanup (and your sub-classes or base class have nothing to cleanup) then you don’t need to worry about either. However when you have resources to cleanup, then you should really implement both. The reason for this is simple: Provide Dispose() method for deterministic finalization, and provide a destructor in case consumers don’t call the Dispose() method.

    And for those of you (like me) who hate to waste white space on duplicate code, you can call the Dispose() method from your finalizer, however it is best to consider some Microsoft recommended best practises when doing so.

    Pattern For Finalization

    This pattern is based on this article by Joe Duffy. The following example illustrates the pattern best:

    private bool isDisposed = false;
    public void Dispose()
    {
                Dispose(true);
                GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
                if (isDisposed) return;
                // General cleanup logic here
                if (disposing)
                {
                            // Deterministic only cleanup
                }
                else
                {
                            // Finalizer only cleanup
                }
                isDisposed = true;
    }

    ~MyClass()
    {
                Dispose(false);
    }

    As you can see, there is a bool switch to determine if the Dispose logic applies to finalization or not. This pattern has some advantages when it comes to inheritance. For example, overriding the Dispose(bool disposing) method in a sub-class lets you customise how finalization will occur, without needing to provide the destructor or Dispose() methods (since via inheritance your class already has those methods and implements IDisposable). Also, we track if the object has already been disposed so that we don’t do it again. Finally, the call to GC.SuppressFinalze(this) means that since the object has been properly disposed, there is no need to call the destructor (ie. suppress finalization of this object). Make sure that call goes after the call to Dispose(true) : this ensures that if the Dispose method fails (raises exception) that the destructor will still execute again later and reattempt to cleanup the object.

    Nappy Poo Fear!

    I mean, Happy New Year!

    I know I haven’t posted in a while, but there’s good reasons. Those who know me know that we had a new arrival just before Christmas, a beautiful baby girl, Isabella Maria Nagy. Click here for photos.

    Chumby

    So enough with the personal stuff, lets talk about what I got for my birthday (just before christmas). Recently, Chumby was released in Australia. I really liked the concept and since it was the only thing I put on my birthday wish list, it was no surprise that I got one for my 31st.

    Chumby is a little touch screen device that shows widgets. What it shows is completely up to you. It connects to your wireless internet and downloads news, weather, time, games, music, video, and more. It can be used as an alarm clock (has a ‘night mode’) so you can wake up to your favourite internet music channel. You can use it to monitor your twitter updates, eBay auctions, mail inbox, basically anything that has a widget written for it, which is almost everything.

    Under the hood each widget is a Flash application. You can write your own widgets and upload them to the Chumby site for everyone to share. I was thinking of creating a TFS Build Notification tool for it. Hardly something useful on an alarm clock right? Well Chumby doesn’t have to be just an alarm clock. Think of it as a feed of information available anywhere in your house or office. My Chumby sits on my work desk currently, but I am thinking of getting another one for the kitchen and maybe lounge room as well!

    The management of your widgets is extremely easy. You don’t need to install anything on your local computer. Once you register your Chumby with the online servers, you can control it via their web interface. By default there is one channel with about 8 widgets pre-loaded, but you can then add/remove widgets as pleases you. If you want, add another channel and add widgets to that channel. For example, you might have one channel for monitoring weather and news widgets only, but in the evenings change to the channel that has all your music and videos, latest clips from YouTube, and Facebook status updates.

    Checkout the website for more information about Chumby.

    Azure Blog – Above The Cloud

    Near the end of last year we saw the release of the Azure Services Platform, a Cloud offering from Microsoft. I’m very intrigued by this and it seems Microsoft have invested a lot of effort into their Cloud architecture.

    Rather than spend any real time talking about it here, I’d like to take the opportunity to announce a new blog that I will run beside this one (both will continue). I am dedicating a whole blog to learning about Azure, since I believe it will honestly impact .Net development going into the future.

    Check it out at its location here: http://azure.snagy.name/blog and subscribe damn you!

    October 10

    Dare To Dream Different

    Recently the DevSta competition came to a close and saw 40 unique entries across a range of categories (games, mobile, gadgets, etc). I personally found it hard to "roll down" after going a hundred miles an hour to submit my entry, down to 0 again when the competition closed. I felt like I should still be doing something, that there were so many more modifications I could make to my entry.

    Now a new competition emerges and it definately looks interesting! Its called: 'Dare To Dream Different' and it boasts a plethora of prizes valued at over $100,000!! The focus of the competition is not just about hacking something together; it seems to focus more on the business aspects and developing a real commercial product. And it focuses on the Micro Framework from Microsoft.

    I think this is a great idea to get the creative juices flowing around what can be done with smart devices. The competition seems to focus on the idea and marketability first, then moves to the development phase. As a result the competition is quite long running and can be submitted in groups of 3 or less.

    It will be really interesting to see what kind of commercial products emerge from this competition. No doubt the winners will attract the interest of hardware vendors around the world. I'll be watching this space keenly!

    Dare To Dream Different Website

    September 30

    Developer Machine Builds for Real Men (and women) - WDS, WinPE, ImageX and Sysprep

    I like to rebuild my machine a lot. I usually install every beta under the sun, and my HDD is usually fragmented within a day of rebuild. So I need an efficient process around rebuilding my desktop and my laptop for developer use. Installing Vista Ultimate followed by Office, VS2005/2008, Sql 2005/2008, Visio, Project, Expression Suite, SysInternals, Reflector, Fiddler, Twhirl, Live Writer/MSN, Firefox, Opera; the list is endless. And these are my standard day to day tools.

    Enter WDS : Windows Deployment Services. Like most developers I have a Server 2008 license (either through TechNet, MSDN, or handed out at any user group these days!) and one of the 'Roles' is WDS. This software lets you specify a boot image and a build image to be deployed via the network. It operates with WIM files, which contain all the information to build a particular operating system and software.

    For example, if you load up your Vista or Windows Server DVDs, you will find a boot.wim and install.wim on those disks. Microsoft uses WIMs for deploying operating systems already, so the infrastructure is already here to build our own WIMs and deploy them. But instead of building a DVD, we'll deploy via a network so that any machine at home can be reimaged at any time.

    WinPE is a boot environment that gives us a command prompt. Generally WinPE is something you boot into, instead of your normal operating system. In fact, there is a boot.wim that contains WinPE, and its available in the Windows Assisted Installation Kit (WAIK) in x86 and x64 varieties.

    Sysprep is a tool build into Vista already. Usually hiding out at C:\Windows\System32\Sysprep, you can also hit it from the Vista Search prompt. It has a command line mode and a window mode. Sysprep performs a very interesting task. It will strip your current installation of all operating system logic such as language, domain, etc. This is known as the "Out of the box" experience (OOTB). If you run Sysprep and reboot, then you will be prompted for all the usual system information, time/date settings, etc. But once you fill those in, you will see your system still has all the programs installed, etc. All it does is "prep" the system for setup.

    Finally, ImageX is a command line tool used to image a machine and create a WIM file. Using this tool we can image a full installation and create an install.wim for our developer machine. Combined with Sysprep, we can create a WIM file that has been stripped of machine specific information.

    So how do we put it all together? Here's some steps around what I've done to give you an idea what's need to get this puppy rolling.

    A) Build your development machine with all the software you want. I found it easy to do this in a virtual machine; I was already using hyper-V on my 2008 server so this suited my needs. The cool thing here is that I've taken a snapshot after every software install, so in future if I want to build a machine with less software, I can just apply the relative image, then continue the steps below.

    B) Sysprep the machin with the OOTB experience, and shut it down

    C) On the machine running WDS, add the WinPE WIM as a boot image

    D) Also on WDS, create a new SHARE where we can put new image files. Make sure you have an account with full access to this folder; doesn't matter if it is password protected, we will see options to specify auth later.

    E) In the share folder, create sub folders called BIN and IMAGES. Copy the binaries from WAIK into the BIN folder (from C:\Program Files\Windows AIK\Tools\x86 or similar). Leave IMAGES empty; this is where we will put our developer image.

    E) Start up the developer machine again; it should detect your WDS and ask you to press F12 : press it!

    F) You will be prompted to choose a boot image. If you have more than one, ensure you choose the WinPE option. This will dump you at a command prompt eventually.

    G) We have to map a network drive to our share on the WDS server. For that we use 'net use' command:  net use z: \\server\share
    This will prompt for user and password. If you have any problems with the 'net' command, just try 'net /?' or 'net use /?'

    H) Time to image: go to Z:\BIN and you should see the files from before, including ImageX. Type this command: imagex /capture c: z:\images\install.wim "Vista Developer Machine" /verify
    This will capture the local C: to the images folder. If you want to image a different drive then feel free.

    WARNING: Be prepared to wait. Imaging takes a while, and the bigger your image/slower your network, the worse it gets. For me, it took about 24 hours, for a 18Gb image on my main network. Think about optimisations for this. For example, if you are imaging a VM and WDS is another VM on same machine, create a virtual network between the two. That way communication never leaves the host machine.

    I) Once imaged, you can close your developer VM. Go back to the WDS machine and add the new image file as an install image. You will also need to add another boot image since WinPE boot image will not boot to the installer. As mentioned earlier you can find boot.wim files on your Vista and Windows Server DVDs. I suggest the latter (which can be used to deploy Vista and Server 2008 images). Now you have a boot image and developer machine install image.

    J) Test it: provision a new VM (or host machine) and do the network boot thing again (F12). This time the Server 2008 boot image is an option, select it. Start following the prompts and you will eventually get an option to select an installation - Select your developer machine.

    WARNING: Be prepared to wait again! Once again, the imaging takes a while.

    K) After system finishes deploying you should have a full working developer machine!

    Further Notes

    The waiting times are somewhat annoying. Creating the machine image is something you really only have to do once, but you might want to automate it a little more to make it easier to deploy versions of a VM (snapshots) with a quick click of a button or PowerShell script. You could modify the WinPE boot.wim image to incorporate the ImageX tools, and a batch file so that you don't have to keep coming back to this article for reference. In fact, an autoexec.bat might even work bundled into your WinPE image.

    Building async in a separate VM can be slow but at least you can provide a nice structure for reusability, while still using your dev machine. Then leave it to reimage over a weekend or whatever when its needed. And you can obviously reimage multiple machines. WDS is great because you can also copy the install.wim files from Vista and Server across as well and deploy those if needed. Basically, no need for hard media any more. =)

    September 29

    DevSta Programming Competition Goes Live!

    Its Monday morning, just after 8am. The DevSta competition starts any minute now. 200 hours and 8 minutes to complete a Visual Studio 2008 project. The brief will be announced any second, and developers all over the country will start madly coding! For 200 hours, wives will be ignored, chores undone, children with no lift to school, washing up pile stacked up on the floor... society will be brought to its knees. Undoubtedly you've heard about the sub-prime market failure in the US? Hurricanes destroying cities? Countries in civil unrest? Its all in anticipation of what happens next, what happens in the next 200 hours.

    The combatants nervously await. The topic will be announced any moment. They glance at the clocks of the 3 machines humming nearby. They all report different time! A quick Google for "time" indicates that there are still a few precious seconds to go.

    Pressure in the bladder. Do I have time to go for #1? I deliberately built a toilet in my study for just this reason. A quick cost/benefit analysis indicates that its probably better to go now, because hospitals don't allow electronic equipment.

    Finally, the climax. A new email in the inbox from Microsoft... the topic is announced. It says to go to the website for the competition brief. Doing as asked reveals nothing though. Could the email have been sent 3 minutes too early? Could it be a cache issue? CTRL+F5 is repeatedly pressed about 100 times.

    The countdown clock on the website has ticked over! It now says 200 hours 8 minutes remaining. Yet there is no brief! Feeling like I'm falling behind already...

    In the end its the helping hand from a friend that reveals the PDF containing the brief.

    Game on!

    August 29

    DEVSTA - The programming competition for star developers!

    Although it hasn't been officially announced by Microsoft yet, the information was revealed on the OzSilverLight mailing list today that there will be a programming competition for Australian developers starting in September.

    Here is the URL: http://devsta.microsoft.com.au/

    What's really interesting about this particular competition is that it is offering some seriously cool prizes! For instance, first place is an all expenses paid trip to Mix09 in Vegas next year, an XBOX Elite plus games, and a MSDN subscription.

    The "theme" of the competition will be announced on 29th September, and then it will be open slather. Developers will have exactly 200 hours and 8 minutes to complete their submission for the competition.

    So start stocking that jolt cola and be ready on 29th Sept to compete to become the next DEVSTA!

    August 20

    System.IConvertible - Its not a Ferrari

    You might be familiar with the System.Convert class, which has a number of methods for converting from/to different types. For example:

    short s = Convert.ToInt16(int.MaxValue);

    We live in a world of casting and you might find this code somewhat pointless. After all, it will still raise StackOverflowException and lose precision with floating poing conversions, so what's the point?

    The convert class is capable of converting an instance of ANY type into one of the common base types (sting, int, ulong, char, etc). If a type implements the System.IConvertible interface, it can define how conversions of that type will occur.

    Lets consider a (not so practical) example. Say we have a product class with the following properties:

    public int ProductId { get; set; }
    public DateTime DateAvailable { get; set; }
    public string Name { get; set; }

    Our Product class also has a parameterless constructor. In this example, we also make the Product class implement the IConvertible interface. This forces us to implement 16 methods and 1 property. Those methods all relate directly to conversion. For example, here's the implementation of one of those methods:

    public ulong ToUInt64(IFormatProvider provider) {
          return (UInt64)ProductId;
    }

    What we are saying here is that if someone tries to convert our Product instance to a ulong then it will simply assign the ProductId. Our test code looks like this:

    Product p = new Product { Name="Car", DateAvailable=DateTime.Now, ProductId=7 };
    UInt64 i = Convert.ToUInt64(p);
    Console.WriteLine(i);

    The output is the number "7" because that is how our implementation of IConvertible tells the Convert class to handle conversions to UInt64.

    Simple eh?

     

    July 01

    Rolling back a changeset in TFS

    In TFS 2005 and 2008 there is no easy way of rolling back a changeset. Sure, you can do a "get specific version" of each file from before the "bad" checkin occurred, and then check the older version back in. But this really sucks if you have a lot of files in your changeset.

    Luckily the Team Foundation Power Tools can help you here. One of the command line options is as follows:

    tfpt rollback /changeset:xxxx

    Here, you simply replace xxxx with your changeset number, and the power tools will take care of the rest.

    First, it will "get latest" of the workspace. Next it will perform an operation for each file that is required to roll it back. For example, if you added a file, it performs a delete. If you deleted a file, it performs an undelete. If you simply edited a file, it will get the code from the changeset previous for that file. The result on the command line indicates which changeset was used for each file it rolled back.

    It then pops up a window requesting confirmation for all the files. After this, it checks out all those files it will roll back and you can then check them in (or only check some in if you so wish).

    One caveat with this process is that when you are executing the command line, you might get an error: "Unable to determine workspace". This simply means you are not currently in a folder that is part of a workspace. Change directory into a folder that is stored in the workspace you want to use (for those that use multiple workspaces with different folders).

    Good news is that Rosario will have rollback features incorporated. Check out the help for rollback for more information:

    tfpt rollback /?

    Technorati Tags: ,,,,
    June 13

    Destroy Work Item : Is it really gone?

    This week we had a situation where we needed to remove a work item from the TFS database completely. You can delete a work item in Team Explorer however this just marks the row in the database as deleted and as such your database will always grow, never shrink.

    The Visual Studio Team System 2008 Team Foundation Power Tools give us the ability to destroy a work item with the 'destroyWI' call. Here's the command line syntax:

    tfpt destroywi /server:<SERVER> /workitemid:<ID>

    The 'intention' is to delete all instances of the ID from the database, and all related data, and in truth it comes pretty close. However there is one table it misses: 'WorkItemsWere'

    If you look at your TFS database instance you will notice there are actually a few databases. One of them is 'WorkItemTracking' and this database contains all the tables related to work items. The astute might also notice that each of the databases in their instance seems to match each of the web services provided by TFS. Coincidence?

    In the 'WorkItemTracking' database you will see a number of tables that all contain work item related data. In particular, notice the two tables: 'WorkItemsAre' and 'WorkItemsWere'. The 'Are' table contains the current state of a work item while the 'Were' table contains its history.

    For example, work item 1234 is modified several times. First it is opened as a bug and assigned to 'triage'. Then triage moves it to the developer who fixes the bug and resolves it with comments, where it is assigned back to the user who opened it. The bug isn't fixed, some additional comments are inserted, its assigned back to the developer, and so on. If you are familiar with work items, you will be able to identify the 'History' section where you can view the audit history. This essentially is what is stored in the 'WorkItemsWere' table. Makes sense now right?

    Yesterday I did a destroy of a work item and discovered that all the various tables had all instances cleaned up, except the 'WorkItemsWere' table. I contacted the VSTS team who indicated that this is indeed a bug and it is now logged in their own work item system (oh the irony!).

    What to do in the mean time? Well they assure me it is safe to delete the orphaned database rows, despite the general consensus on the net not to mess with the database directly. I can confirm however that this is the only table with orphaned data. And I'm sure this will be fixed up in a future release of the power tools. All round I quite like the TFPT and haven't even bothered with the multitude of 3rd party components that put a UI in front of it: real men use command line!

    June 01

    Advanced Generics

    I've recently been reading this book by Jon Skeet about C# 2 and 3, and it got me all inspired to write about generics. Jon's great; he's extremely active in the C# and Java community, and recently responded to an email question I had in less than 10 minutes! I'm finding the book insightful and useful and greatly enjoying my bus rides to work when I get to read it.

    This post is going to assume you are familiar with using generic classes like List<T> and Nullable<T>. So lets start with the syntax for declaring our own generic class:

    public class Monkey { }
    public class Animator<T> {
        private T instance;
        public Animator(T t)
        {
            instance = t;
        }
        public void MoveOnce() { }
    }
    Animator<Monkey> animator = new Animator<Monkey>(new Monkey());
    animator.Move();

    This is pretty simple: the Animator class accepts a generic type T and requires you pass a T in its constructor. The MoveOnce() method is empty at the moment, we'll get to that later.

    Currently our generic Animator class is somewhat type-safe: we can only pass instances of T to its constructor, but we don't really know much about T. We'd like to be able to move our instances (such as a monkey) so we need to define some things about what kinds of T we are willing to accept. Lets go back to our Monkey class for a moment and define an interface for it:

    public interface IMoveable {
        void Move();
        void Stop();
    }
    public class Monkey : IMoveable {
        public void Move() { }
        public void Stop() { }
    }

    Great! We've decided that the fact a Monkey can move and stop is pretty general, and is probably something other animals can do, so we've declared an interface to indicate our monkey has those capabilities. We might also define IEater, or IDungFlinger. Now we can revisit our generic type in our Animator class definition as follows:

    public class Animator<T> where T : IMoveable
    {
        private T instance;
        public Animator(T t)
        {
            instance = t;
        }
        public void MoveOnce() {
            instance.Move();
            instance.Stop();
        }
    }

    This is where the magic begins. We've placed a constraint on our generic type, stating that it will only ever accept a type that implements our IMoveable interface. If we try to use the Animator class with something else, we will get a compile-time exception. Even better yet is that our development environment knows that since our instance will always implement IMoveable, it therefore must have a Move() and Stop() method, therefore we can call it anywhere in our class; in this case the MoveOnce() method.

    You can declare more than one generic type in your class definitions. Imaging a class that facilitates a race for monkeys, whether they be chimps, gorillas, or marmosets. Consider this generic class declaration:

    public class Race<T, U> where T : Monkey where U : Monkey {
        public Race(T monkey1, U monkey2) { }
        public void RunRace() { }
    }
    public class Marmoset : Monkey { }
    public class Chimp : Monkey { }

    Here we have defined that our class accepts 2 generic types: T and U. We have further restricted them that they both have to inherit from the Monkey class. Here's some example calls using this new class:

    Race<Chimp, Marmoset> race1 =
          new Race<Chimp, Marmoset>(new Chimp(), new Marmoset());
    Race<Monkey, Chimp> race2 =
          new Race<Monkey, Chimp>(new Monkey(), new Chimp());
    Race<Marmoset, Marmoset> race3 =
          new Race<Marmoset, Marmoset>(new Marmoset(), new Marmoset());

    As you can see that anything that inherits Monkey is valid. Of interest, the second example shows that even an instance of Monkey is valid. This shows that the where clause in our type restriction means anything that inherits from X or is X.

    Finally here are a couple of extra cool things you can do with generic type restrictions as general non-monkey related examples:

    public class TestCase1<T> where T : class { }
    public class TestCase2<T> where T : struct { }
    public class TestCase3<T> where T : IDisposable, IMoveable, IComparable { }
    public class TestCase4<T, U> where T : U { }
    public class TestCase5<T, U> where T : U, IMoveable { }
    public class TestCase6<T, U> where T : class where U : struct{ }
    public class TestCase7<T, U> where T : class where U : struct, T { }

    TestCase1 demonstrates that we can force the type to be a reference type.
    Likewise TestCase2 ensures that the type must be a value type. How is this useful? Well consider a generic class that performs expensive operations such as copying from one list to another. Reference types are just pointers and therefore inexpensive to copy around, thus ensuring only reference types are allowed in our class could be quite useful.

    TestCase3 shows that we can ensure T implements multiple interfaces.
    TestCase4 shows that one generic type can be forced to inherit from another. An example of an implementation might be:

    TestCase4<Chimp, Monkey> test = new TestCase4<Chimp, Monkey>();

    This is valid because Chimp inherits from Monkey.
    TestCase5 shows that a type can be restricted to inherit as well as implement interfaces.
    TestCase6 demonstrates that one type must be a reference type while the other can be a value type.

    The last TestCase7 is somewhat interesting. Its declaration indicates that T is a reference type, and U is a value type that must inherit from T. How can this be? It essentially states that you must pass a struct that inherits from a class. But C# won't let you declare this.

    To be honest at first I didn't know the answer to this. Thus the email to Jon, and his explanation was simple and it made sense: interfaces are reference types. Hopefully you are aware that structs can implement interfaces also (but can't do inheritance), so we might define a new animal as follows:

    public struct Mouse : IMoveable {
        public void Move() { }
        public void Stop() { }
    }

    Then we can legitimately use the TestCase7 syntax:

    TestCase7<IMoveable, Mouse> test = new TestCase7<IMoveable, Mouse>();

    Then of course, valid values for an IMoveable are a Chimp, Marmoset, or even another Mouse, while of course you can only use a Mouse for the second type.

    Hopefully this has given you a better idea of what you can do with generics.

    May 29

    Contravariance, Covariance, and Generics

    The common question is: what the hell is contravariance and covariance?

    Ok so you are familiar with casting right? In C# we can do this:

    public class Animal { }
    public class Monkey : Animal { }
    ...
    Animal a = new Monkey();
    ((Monkey)a).FlingCrap();

    We can also do this:

    public void MoveWest(Animal a) { }
    ...
    MoveWest(new Monkey());

    Because the 'MoveWest' method accepts the narrowing type 'Animal' it is said to support 'Contravariance'. If the C# compiler forced us to only pass exact types, then it would be considered 'invariant'. Likewise C# methods support covariance, in that we can return a narrower type and cast the resulting instance to its correct form.

    There are parts of the .Net framework however that aren't so flexible. In this case, I'm talking about generics.

    Consider this for example:
    List<Monkey> monkeys = new List<Monkey>();
    monkeys .Add(new Monkey());
    List<Animal> animals = monkeys;

    Unfortunately this does not compile. We get the following warning:

    Cannot implicitly convert type 'System.Collections.Generic.List<FeaturesCsharp2.Monkey>' to 'System.Collections.Generic.List<FeaturesCsharp2.Animal>'

    Why is this? Monkey inherits Animal, so the list conversion is perfectly safe. Well this is one case of invariance. But here's the kicker: word on the street is that the CLR actually supports contravariance of generic lists; its just the C# compiler that doesn't!