Saturday, May 30, 2009

One of the key changes in Visual Studio 2010 is the start of a move to a fully managed code implementation. Several aspects of the product are implemented in managed code using the Managed Extensibility Framework (MEF) - see Visual Studio 2010 New Features, Extensibility Points and Partner Opportunities for the full detail, and watch this video by Paramesh Vaidyanathan and Rico Mariani for an overview of the direction Microsoft is taking here.

I want to see how easy it is to create a simple extension for Visual Studio 2010, in terms of development and deployment, and so I start by downloading the SDK. This SDK includes all the bits needed for developing extensions to Visual Studio, along with a number of project templates to get you started.

Notice the description of the selected template - this isn't just a blank project, it actually implements an editor adornment, which in this case highlights every character 'a' within the editor document by putting it within a box.

What I would like to do as a first project is to implement a similar editor adornment, but in this case look for block comments which contain the text "TODO:" as the first non-whitespace text in the comment, and highlight the entire comment in a graduated red box (similar to the blue selection box we have in VS 2010). This highlight will extend to the first line which isn't a comment (or which is a comment, but only has whitespace characters). So something like this:

So I create a new Editor Text Adornment project, and take a look at what comes out

We get two C# files and a .vsixmanifest file - which I guess we should take a look at first. Double clicking on this opens up a property editor

I'm not going to dig into this in detail for the moment, but looks like this gives us the ability to define what we want packaged up with our extension in terms of additional files and referenced packages and assemblies. We can also name our extension and define some icons which appear in the Extension Manager. Finally we can restrict supported versions of Visual Studio and the framework if we so desire.

OK, now lets look at the classes. AdornmentFactory.cs is responsible for two things - firstly it defines a new layer onto which our class will draw its adornments.

And secondly the class itself implements IWpfTextViewCreationListener which allows it to hook into IWpfTextView events in the TextViewCreated method.

I don't like the way this is implemented - ie having the contructor "do stuff" with a class which is never used, a very non-intuitive bit of code in my opinion, it would look better with a static method which itself calls the constructor, eg ScarletCharacter.RegisterView(textView).

The constructor of our adornment class itself simply caches the view, and the adornment layer which we registered for this view, along with some graphics objects (Brush, Pen etc not shown above) and registers a LayoutChanged handler for this view.

This event handler gets details of each change made in the editor, and is called when the editor is first opened also. The CreateVisuals implementation by default deals with highlighting all 'a' characters in the file, but we want a different implementation. So lets rename this adornment class to TodoHighlighter and we should get away with changing CreateVisuals to achieve our purpose.

This is similar to the original implementation, except here we go through all lines in the editor, looking for those which start a TODO block, and for each of these determine the extent of the block and then create the highlight based on a SnapshotSpan. TODO blocks are detected with these methods:

Finally we can add some sparkle to the default brush used to draw the highlight - we wanted a gradient red, similar to the blue used for normal highlight in the WPF based text editor. Lets modify the constructor code as follows:

We should be ready to rock. Lets F5 this bad boy and see what comes out. Well, as is so happens, F5 spins up a new visual studio instance running under the debugger and by default took ages. I stopped the debugger, changed Options to disable Historical Debug, and tried again - much better.

So in this debug Visual Studio, I create a console app, and modify Program.cs with a TODO comment, and tada:

Great stuff, maybe needs some tweeking but the concept is proven. Now what do we do about installing this into Visual Studio? Lets examine what has actually been generated for us.

This is the contents of bin |> debug for this project. We have what we would expect, but also this TodoCustomHighlighter.vsix file. This is actually the zipped package file which Visual Studio now recognises for extensions. If we go into the Extension Manager, we should be able to select this and install it.

Hmm, no options there for installing from a local drive. Lets just double click on the vsix file. This seems to work fine:

So I click install, then restart Visual Studio as suggested. Nothing, no sign of my extension in the Extension Manager, and no highlighting of my TODO comments.

Perhaps it didn't hear me. I try installing from the vsix again. This time it fails with the following error in the log:

Install Error : Microsoft.VisualStudio.ExtensionManager.AlreadyInstalledException: TodoCustomHighlighter is already installed.

This is weird - looks like Visual Studio recognises that the extension has been installed, but for some reason is not running it, or even acknowledging its existence. Looking at the options dialog, there are some extension manager options.

This has the option Load extensions from my local application data folder, but this is unchecked and also disabled. I am running the Windows 7 RTM, so this may be a UAC issue. I shut down VS and restart in escalated mode by holding down Ctrl-Shift whilst clicking the Visual Studio taskbar icon. This allows me to check the Load extensions... option - great.

Except that even now, before or after restarting Visual Studio, I still don't get my "installed" extension. Something strange is going on here. Time to check the event log and the registry to see if we can find out what is happening.

OK I find the extension in HKCU\Software\Microsoft\VisualStudio\10.0Exp\ExtensionManager\EnabledExtensions containing:

Name: TodoCustomHighlighter..fbe86c05-ea59-4bb6-b982-b1478430e535,1.0
Value: C:\Users\Chris\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions\TodoCustomHighlighter\1.0\

Looking for that specified directory, all I have is C:\Users\Chris\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions - which is empty. Possible that something went wrong because I didn't have Load extensions from my local application data folder enabled when I first installed the extension. I will delete this registry value, and see if that allows me to install again.

Nope, same problem. Although I notice the TodoCustomHighlighter\1.0 folder has appeared in the root of the C drive for some reason. Moved this to the path specified above, but still doesn't load.

It's annoying, but I am going to have to leave it there for now. I will monitor some of the VSX blogs for any solutions or workarounds to this problem and update this post when I have more info, but for now it looks like I have a working extension which just can't be installed.

EDIT: I found a workaround by re-reading Scott Hanselman's post on the Demo Dashboard extension - if you just drop the DLL into C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\Components and restart Visual Studio, the extension is installed, although still isn't listed in the Extension Manager. Perhaps this area isn't quite there in this beta 1 release for home grown extensions?

ADDITIONAL: Finally worked it out - I noticed that I could download and install .vsix from the Visual Studio Gallery but that these had an additional part to the filename beneath the Extensions area in AppData. I also noted that I left the Author field blank in the .vsixmanifest file - so I fill this in with "roundthecampfire", and replace the name GUID with a new one so that this looks like a new component.

Now if I rebuild all and reinstall from the .vsix file, it shows success (as it did previously), but if I start Visual Studio it's a different story:

Finally - I have what I wanted all along, a standalone installer file for my extension, and a good user experience for installing it, enabling/disabling it, and for uninstall. The process was tougher than it needed to be for me, but this is beta software, and I guess I should have taken more notice of the little red exclaimation mark next to Author in the .vsixmanifest editor. Hopefully come the RTM this will cause a compilation failure, or an install failure rather than feining success.

Saturday, May 30, 2009 3:45:55 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Thursday, May 28, 2009

A number of enhancements have been made to the intellisense and refactoring features build into Visual Studio 2010 which should greatly enhance support for real test driven development. This post documents my investigation into how well this works in reality.

First I need to recap what I mean by "real" test driven development. This is where each test is written before the code itself, which assists the developer in focussing on the requirements, and essentially defining these requirements through the test alone. Once the test is written, classes and method stubs are added in order to allow the project to compile, the test is executed (and fails), then the classes & methods are updated with the required functionality, and the test re-run to ensure that it passes. See Test Driven Development on wikipedia and the book Test Driven Development by Kent Beck for further reading.

So to use an example that has never been done before (not) lets implement a calculator class, and create a class library (CalcLib) and related test assembly (CalcLib.Test) in a new solution. Add a reference from CalcLib.Test back to CalcLib.

Lets start by adding a test for the constructor - we (arbitrarily) decide that the constructor should initialise the running total to whatever we ask for, so add a new test class CalculatorTests.cs to the test project, and add the first test ConstructorInitialisesTotal to this class.

Now if we start typing the test, by created a new instance of the Calculator class, something annoying happens with intellisense - the test class itself is the default choice, so even if we type Calculator in full and type the first parenthesis, it autocompletes as CalculatorTest instead, and we have to Ctrl-Z to get what we wanted. Grrrr.

Notice that intellisense now has an initial item which says <Ctrl-Alt-Space> - type that - I dare you! This switches intellisense into Consume First Completion Mode, which is what we have been missing all along. Now if I type = new Calculator(); I am allowed to type this without interference, and I see the blue smart tag underline beneath Calculator. A swift Ctrl-. gives me the Generate... menu:

So click on Generate class for Calculator - right? I must admit I already had misgivings before I clicked on this, and this proves to be correct - click on this option and you get a nice fat Calculator class in a Calculator.cs source file and, sadly, inside your CalcLib.Test project, not inside the CalcLib project. This is unfortunate, being as this functionality is in support of TDD, it would have been good to see some intelligence here, ie noting that the current proj is a test project, and has a single reference to another project in the same solution, and at least give us a third option in the menu such as Generate class for Calculator in CalcLib project.

OK, not as good as it should have been. Click on Generate other... instead - this is more long winded, but gives us the flexibility that we are after:

A quick flip of the project menu, press OK, and presto - we now have Calculator.cs in our CalcLib project - is nice. The solution should now build correctly.

Still not much use, because we have an empty test testing an empty class, so lets expand the test firstly by adding a double parameter to the call to the Calculator constructor, thus:

Clicking this gives us a constructor taking a double value as a parameter (albeit it generates a spurious backing property for this parameter, which we don't want in this case - however if it had prompted for a name, we could have added the Total property in one hit, never mind).

Now lets add an assertion that the contructor sets the Total property, and in so doing generate this property in the Calculator class.

If we take the Generate property stub... option and complete the assertion, we now have our test complete and the Calculator class in a compileable state - so lets compile and run the tests. Oops, it doesn't build - the property it generated for us is the wrong type, it can't really infer the type from that overload of Assert.AreEqual, so it has a guess.

Lets try that again, but this time use the generic version of AreEqual so that we know the concrete types for the parameters to this method - hopefully that will allow Generate property stub to correctly guess the type?

Which generates the property as follows:

Much better, so now we CAN compile and run the tests with a Ctrl-R, A and lets see what we get...

Well that sucks - it failed, why? Oh, maybe because we haven't actually implemented the constructor yet - lets do that now.

Now we can build and run the tests one last time -

Great, so we have implemented a test which defines our requirements, observed that the test fails befored the requirement is implemented, and finally observed that once implemented the test passes.

Visual Studio 2010 goes some way towards supporting this method of development, although we have seen a few shortcomings in this beta 1 version. Hopefully at least the issue with generating code within the referenced assembly rather than the test assembly itself can be addressed prior to RTM.

Addendum

Got a great response from Karen Liu, Lead Program Manager on the C# and VB IDE team regarding my questions above, and a quick search revealed some great channel 9 videos she has produced in this same area, especially this one which has the exact same topic as this blog post, and I am embarrased that I didn't spot this beforehand...

Regarding the first issue - the fact that Generate class only generates within the current assembly: the thinking here is that to iterate over referenced assemblies might slow the presentation of the Generate menu, hence the decision was made to only generate within the same class, and refactor later, or to use the Generate other function, as I suggested above.

Regarding the spuriously named property generated with the constructor - Karen had a great suggestion - use a named parameter (C# 4.0 feature), which the Generate constructor function picks up on as expected, so:

Gives us a Calculator class which is already exactly what we need - we don't need to create the Total property in a later step as we did before.

Thanks for the suggestions Karen - looking forward to seeing what we get in the next release!

Thursday, May 28, 2009 10:57:05 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Wednesday, May 27, 2009

One of the major new features in VS2010 is Historical Debugging. This feature automatically instruments applications running under the debugger, causing key events to be logged into trace log files. These trace logs are integrated with the VS2010 debugger, and enable the developer to step back through these events when looking for clues. It is no longer necessary to set a breakpoint before the point at which the bug occurs.

There are two levels of logging supported by Historical Debugging, the first designed to capture events at the OS / Framework level - such as registry access, file access, exceptions etc. The second level supports instrumentation of methods and parameters within your own code (and obviously has a significant impact on performance, although we will dig into that a little later in this exercise). This is all set up within Options |> Historical Debugging |> General:

Historical Debugger Operation

In order to test this feature, I have cobbled together a little console app which does some file writes and reads as well as writing to the console. I have also introduced a bug which should give us a FileNotFoundException somewhere in the code, but which is immediately caught and swallowed - something which would previously have hindered debugging. The main program is simply:

This makes use of two utility classes, one for creating a temporary file containing the given text, and one for writing the contents of a specified file to the console:

So now I can F5 this into the debugger, and immediately see something new:

The Debug History window gives us the ability to suspend a running application at any time, and then look through the historical data captured so far. We can see some failures occuring in that console output, so let's do that now. A list of eventds is presented in this historical view, and scrolling up a little we can see some interesting events prior to the console "Failed" output (note that Console output is not treated as an event by default - I have enabled this in Options |> Historical Debugging |> Diagnostic Events):

We can see now that an exception has been thrown and caught, and the detail of this exception actually gives us the reason - the filename has a spurious $ on the end. We can also see this in the File: Access event above. However, assuming we didn't get the detail we needed as this point, we can switch to Debug Tree view, at which point we can take a look at our own call hierarchy - eg select the File: Access event, then click on Show Tree View:

Here we can see a lot of useful information - we can see the actual call to FileOutputter.WriteFile and the parameter value supplied. Also, if we double click on this, we can see the relevant line in the source file, and can even set watches for values which have been logged (eg the filePath method parameter) - although anything which has not been logged (such as local variables) will show "[Historical Data Has Not Been Collected]". 

This is all clearly an invaluable resource for if not finding a big immediately based on the historical data, then at least giving us a good idea as to where we should set our initial breakpoint prior to a traditional debugging session.

Clearly we don't get any of this for free, so lets now dig into some of the performance aspects.

Historical Debug Performance

In order to get some useful performance stats, I have modified the outputter class to instead just keep a running total of the string lengths, and modified the main routine as follows:

So we repeat the main loop 5,000 times, which should be enough to get some reasonable numbers for overall execution time, and enough to get some relatively significant trace log files. The test is repeated several times (results are averaged) for three setups, all running under the debugger, but once with Historical Debug disabled, then enabled in Events only mode, and finally in Full mode.

As expected, when running with Historical Debug enabled, the performance impact is very significant (two orders of magnitude slower) albeit this is an extreme test with logged events occuring continuously in a tight loop, so this should be nowhere near as significant in typical client (eg WinForms) applications. However, this does signify that in many cases this technology would not be appropriate for debugging server apps.

One slight anomaly is that the full historical mode actually runs quicker than the events only mode. It would be interesting to find out why this is, possibly due to the full mode doing some sort of IL weaving which actually proves to be more efficient in a simplistic piece of code like this.

Anyway, performance issues asside, this looks like a very interesting bit of technology which will prove highly useful in debugging intermittent or deeply buried issues in client applications. Don't forget to disable it when debugging your server code though.

For more detail check out this video on channel 9 which shows it all in action.

Wednesday, May 27, 2009 11:55:37 AM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 
Tuesday, May 26, 2009

Following my usual technique of learning a new technology by blogging about it, I have decided to start a series covering new features in Visual Studio 2010 and .NET Framework 4.0 / C# 4.0 (these posts will be based on Visual Studio 2010 Team System Edition, Beta 1, which is available at that link for public download).

I will start by looking at some of the basic new VS2010 features, and then go in depth into some of the more extensive new features, such as the Architecture Browser, Data Modelling and Code Metrics. Following this I will look into what's new in .NET 4.0 and C# 4.0, with a little help from my trusty Reflector.

Posts to follow soon, and will be indexed from this entry.

Tuesday, May 26, 2009 1:47:57 PM (GMT Daylight Time, UTC+01:00)  #    Comments [0]  | 

Theme design by Jelle Druyts