November 2005 - Posts

In my previous post about browser sniffing for Windows XP MCE in ASP.NET 2.0 I alluded to a bug I encountered when trying to override new browser capabilities in a .browser file. As I explained in more detail there you can define new browser definitions by just adding a .browser file to the App_Browsers directory of your web application.

All browser definition inherit from the default browser definition. You can add new capabilities to it like so:

      <browser refID="Default">

            <capabilities>

                  <capability name="capability_1" value="1" />

            </capabilities>

      </browser>

But overriding its value like this:

      <browser refID="Mozilla">

            <capabilities>

                  <capability name="capability_1" value="2" />

            </capabilities>

      </browser>

or this:

      <browser id="TestBrowser" parentID="Mozilla">

          <identification>

              <userAgent match="TestBrowser" />

          </identification>

          <capabilities>

              <capability name="capability_1" value="3" />

          </capabilities>

      </browser>

fails. Leaving out the default browser bit and just overriding the value set for the Mozilla browser works. I have submitted a bug in the MSDN Feedback Center for this issue (bug ID FDBK40924) with an attached sample web application and steps to reproduce it. The User Agent Switcher extension for Mozilla Firefox comes in very handy to test this. You can use this User-Agent string to match the TestBrowser definition:

       Mozilla 4.0 (compatible; TestBrowser 1.0)

Please try to reproduce this bug on your system and vote for it in the MSDN Product Feedback Center. Otherwise it probably doesn't stand a chance of being fixed in the next service pack of the .NET Framework 2.0.

Since last week I am involved in a project to develop an ASP.NET 2.0 website that should work in Windows XP Media Center Edition 2005.

We want to detect if the web site is running on a PC that has Windows XP Media Center Edition 2005 installed. ASP.NET has built-in browser sniffing capabilities, but ASP.NET 2.0 does not ship with detection for Media Center Edition. Fortunately, adding this is quite easy.

ASP.NET 2.0 has a hierarchical model for matching the User-Agent HTTP header sent by the browser. In 2.0 the browser sniffing configuration is no longer a humongous section in the machine.config file. It consists of several .browser files in the folder: %WINDIR%\Microsoft.NET\Framework\v2.0.50727\CONFIG\Browsers. It is possible to add extra “sniffers” as .browser files in the App_Browsers folder of your web application. This a part of the ie.browser file:

<browsers>

    <browser id="IE" parentID="Mozilla">

        <identification>

            <userAgent match="^Mozilla[^(]*\([C|c]ompatible;\s*MSIE (?'version'(?'major'\d+)(?'minor'\.\d+)(?'letters'\w*))(?'extra'[^)]*)" />

            <userAgent nonMatch="Opera|Go\.Web|Windows CE|EudoraWeb" />

        </identification>

        <capture>

        </capture>

        <capabilities>

            <capability name="browser"              value="IE" />

            <capability name="extra"                value="${extra}" />

            <capability name="letters"              value="${letters}" />

            <capability name="majorversion"         value="${major}" />

            <capability name="minorversion"         value="${minor}" />

            <capability name="version"              value="${version}" />

(…)

        </capabilities>

    </browser>

    <browser id="IE5to9" parentID="IE">

        <identification>

            <capability name="majorversion" match="^[5-9]" />

        </identification>

(…)

    </browser>

    <browser id="IE6to9" parentID="IE5to9">

        <identification>

            <capability name="majorversion" match="[6-9]" />

        </identification>

(…)

    </browser>

As you can see IE “derives” from Mozilla, IE5to9 extends IE and IE6to9 extends IE5to9.

ASP.NET 2.0 makes this information available through the HttpBrowserCapabilities class. An instance of this class is exposed through HttpContext.Current.Request.Browser.

The browser used by the Media Center Shell is Internet Explorer 6.0. MCE comes with some extra ActiveX controls and extra client-side scripting capabilities through the window.external.MediaCenter object. When IE 6.0 is running as stand-alone browser on a Media Center PC it has access to the ActiveX controls, but not to the window.external.MediaCenter object. Fortunately, the user agent string has the information that indicates in which mode IE6.0 is running. The user agent strings of the various Media Center Editions can be found in this MSDN article.

As the core capabilities are the same as those of IE 6.0 I extended the IE6to9 browser. I added a WindowsMediaCenter.browser file to the App_Browsers folder of my web application with the following content:

<browsers>

      <browser id="IE6to9onMCE" parentID="IE6to9">

            <identification>

                  <capability name="extra" match="Media Center PC" />

            </identification>

            <capture>

                  <capability name="extra" match="Media Center PC (?'version'(?'major'\d+)(?'minor'\.\d+))" />

            </capture>

            <capabilities>

                  <capability name="windowsMediaCenterExtensions" value="true" />

                  <capability name="mceVersion" value="${version}" />

                  <capability name="mceMajorVersion" value="${major}" />

                  <capability name="mceMinorVersion" value="${minor}" />

            </capabilities>

      </browser>

      <browser id="IE6to9onMCEinShell" parentID="IE6to9onMCE">

            <identification>

                  <capability name="extra" match="MediaCenter" />

            </identification>

            <capture>

                  <capability name="extra" match="MediaCenter (?'version'(\d+\.\d+\.\d+\.\d+))" />

            </capture>

            <capabilities>

                  <capability name="runningInMceShell" value="true" />

                  <capability name="mceShellVersion" value="${version}" />

            </capabilities>

      </browser>

</browsers>

For more information about the .browser file format see MSDN.

I used the following Default.aspx page to test the browser sniffing:

<%@ Page Language="C#" AutoEventWireup="false" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

    protected override void OnPreRender(EventArgs e)

    {

        base.OnPreRender(e);

        Response.Cache.SetCacheability(HttpCacheability.NoCache);

        string[] browsers = (string[])Request.Browser.Browsers.ToArray(typeof(string));

        BrowserInfo.Text = "<b>Browser ID</b>: " + Request.Browser.Id

            + " - <b>Version</b>: " + Request.Browser.Version

            + " - <b>Hierarchy</b>: " + String.Join(" | ", browsers)

            + " - <b>MCE enabled</b>: " + Request.Browser["windowsMediaCenterExtensions"]

            + " - <b>In MCE shell</b>: " + Request.Browser["runningInMceShell"];

    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>Browser sniffing</title>

    <script type="text/javascript">

function IsMCEEnabled()

{

    return true;

}

    </script>

</head>

<body>

    <h1>

        Browser Sniffing Info</h1>

    <div>

        <asp:Label ID="BrowserInfo" runat="server"></asp:Label>

    </div>

</body>

</html>

When this page is requested in Mozilla Firefox 1.0.7 the result is:

Browser ID: mozillafirefox - Version: 1.0.7 - Hierarchy: default | mozilla | gecko | mozillarv | mozillafirefox - MCE enabled: - In MCE shell:

When this page is requested in the Media Center Shell on PC with XP Media Center Edition 2005 that has Update Rollup 2 installed the result is:

Browser ID: ie6to9onmceinshell - Version: 6.0 - Hierarchy: default | mozilla | ie | ie5to9 | ie6to9 | ie6to9onmce | ie6to9onmceinshell - MCE enabled: true - In MCE shell: true

Unfortunately I ran into some problems when trying to give the capabilities windowsMediaCenterExtensions and runningInMceShell the default value false by adding this to WindowsMediaCenter.browser:

      <browser refID="Default">

            <capabilities>

                  <capability name="windowsMediaCenterExtensions" value="false" />

                  <capability name="runningInMceShell" value="false" />

            </capabilities>

      </browser>

When I added this (at the top of the file), the values were false for all browsers even when overridden. This seems to be a bug in ASP.NET 2.0 to me.  Another strange thing I encountered was that there seems to be some inappropriate caching going on. When a MCE PC is the first to request the page after an application restart, an ordinary IE 6.0 browser on another PC who comes after the MCE PC is identified as IE6to9onMCEinShell. When the ordinary IE 6.0 is the first browser to request the page, it is the other way around. The MCE PC that comes second is falsely identified as IE6to9. Mozilla Firefox is always identified as mozillafirefox no matter if it comes first or second.

When installing the November CTP of the WinFX Runtime Components, I consistently encountered a problem. I experienced a hang of the setup.exe process at about 90%  of the Loading Setup Components stage. The process took up all the available CPU and the most annoying thing of all was that the process could not be killed. The only way to return my computer to a usable state was to reboot. After about three attempts I decided to dig a little deeper.

I remembered reading a blog entry of Mark Russinovich about unkillable processes. So I downloaded and installed the latest Windows Debugging Tools from Microsoft and LiveKd from Sysinternals. The offending thread in the setup.exe process had two outstanding I/O requests in the IRP list that had not completed: one in AFD.sys and one in tcpip.sys. Since both have to do with networking, after another reboot I disabled my Kerio Personal Firewall and my LAN connection. This time the WinFX setup process passed the problem point. I re-enabled my TCP/IP connection when it wanted to download additional components. Setup completed without further problems.

Thanks Mark for the great tools and blog entries that help diagnose and fix these kinds of problems! Although I don't know what the root cause of the problem is, I can play with the latest WinFX.

To celebrate that images show up again on BloggingAbout.NET, here is a pretty picture I took last weekend in the Geuldal in the Dutch province of Limburg:

Picture of the Geuldal in the Dutch province of Limburg (click for larger version)

You can see the small river called the Geul meandering through the valley where the cows are grazing.
Ever wondered how Microsoft is marketing Visual Studio 2005 Team System in Korea? Even if you didn't, check out this rap video http://www.microsoft.com/korea/events/ready2005/vs_song.asp.

Don't forget to read the very funny lyrics on the bottom of that page, if you don't speak Korean.

Today I am experiencing some very annoying problems with Community Server (CS) as currently configured on BloggingAbout.NET.

For as of yet unknown reasons the BA.NET engine has started to randomly remove src attributes of img tags when rendering my last blog post. In edit mode and preview mode my last post looks fine, but when published the images are missing. It seems to work if the src attribute is the first attribute of the img tag, so I tried to edit my post in source mode to rearrange the attributes. But unfortunately the editor configured at BA.NET decides to mess with my HTML and rearrange the attributes to its own liking just before a post is submitted to the server. So I am unable to get the images to show up ;(

I have had some problems in the past with Community Server. It kept messing with my HTML. The problem then was that CS was configured to filter out any style attributes on HTML elements. How annoying when creating your post post in Word and then copy-and-pasting. The HTML produced by Word 2003 is relatively decent and uses style attributes instead of font tags. I was then forced to use the WYSIWYG DHTML editor which has a very old-fashioned idea of decent HTML: font tags all over the place ;(

Another very annoying thing is that the hosting provider thinks 12:00 PM Central European Time is a good time to reboot the database server used by BA.NET. Probably because they think 3:00 AM Pacific Time is an okay time to do so since nobody is visiting the site in the middle of the night in California ;(

So is it time to seek my own hosting provider and control my own blogging engine? I don't know yet. Moving my old posts over to another blogging engine will probably be a royal pain-in-the-ass. Especially since I use the Gallery feature of Community Server quite a lot. And moving to another domain will probably mean loosing some readers, because my posts will no longer be aggregated on the BA.NET feed.

[Update 2005-11-15: The disappearing src attributes from img tags were caused by the installation of a prerelease of SP1 of Community Server 1.1. The problem is fixed now.]

Last Tuesday I encountered a problem with building code and checking-in code from within the Team Edition for Software Architects of Visual Studio 2005. To explain what went wrong, let me first explain the situation and tie in with some of my previous posts.

At home I run the Team Suite Trial SKU of Visual Studio 2005. My Team Foundation Server was running inside a Virtual Machine on a laptop. I had created a Team Project there with a "clean build" code analysis check-in policy.

I took this Virtual Machine with me to the office of LogicaCMG I work at. There I moved the Team Foundation Server (TFS) over to a machine running Virtual Server. On my laptop I installed a Virtual Machine running the Team Architect SKU that had been prepared by a colleague. This Virtual Machine is joined to a domain, while the TFS is running in workgroup mode. You might think that this might be a problem, but this works just fine. You can connect from a Team System Client joined to a domain to a TFS running in workgroup mode. The account name you login with on the client doesn't even have to match with an account on the TFS. When you connect to the TFS you are prompted once for a username and password.

After connecting to the TFS, I could fetch the project I created at home from source control. But when I wanted to compile the code I got the following error:

Screenshot of a code analysis tool error in Visual Studio 2005 Team Architect (click for larger version)

NullReferenceException was thrown from the method Microsoft.Build.Tasks.CodeAnalysis.GenerateFullPathToTool(), causing an unexpected failure of the CodeAnalysis task. I guessed this was due to the fact that the Team Architect SKU does not support code analysis. You can see this through the absence of the Code Analysis tab in the Properties window for a Visual Studio Project. This a chart (from MSDN) that compares the features of the Team System Client SKUs:

Chart with a comparison of the different Visual Studio 2005 Team System Client SKUs (click to view image)

But the error message was not really a polite way to say that code analysis is not suppored. A small investigation showed that I do have a C:\Program Files\MSBuild\Microsoft\VisualStudio\v8.0\CodeAnalysis\FxCopTask.dll file. This assembly is called by MSBuild when running the code analysis after compilation. Using .NET Reflector showed that the offending method is contained in this assembly. MSBuild tries to run code analysis because of this line in the .csproj file:

<RunCodeAnalysis>true</RunCodeAnalysis>

I could not find a way to turn this off in the Team Architect SKU other than through editing the project file in Notepad. The project compiled fine however, so I tried to check-in the code to Team System Source Control. This did not work. I got the following check-in policy violation:

Screenshot of a check-in policy violation in Team Architect when code analysis fails (click for larger version)

The only way I found to circumvent this problem was to ignore the policy violation and override the policy to check-in anyway. So this begs the question: are architects not supposed to run code analysis if they check in code for a Team Project? How are architects supposed to collaborate on code when they are part of a Team Project that has a code-analysis check-in policy?

In most projects I work on, the application architect also has a reviewing role and is responsible for the quality of the code. This means that he or she should be the person setting the code analysis rules. But maybe Microsoft is aiming Team Architect at architects who are not involved in coding. But even if the architect does not write code and only designs the application using the Whitehorse designers, code still gets generated. This code has to be checked in by the architect and he/she might run into the code analysis problems I described above.  If this is by design and not just a bug on my installation, it is an extra reason for me to get an upgrade to a non-trial version of Team Suite.

If you have any ideas about this, please let me know, by leaving a comment.

[Update 2005-11-16: In response to a post in the MSDN Forum for Team System, Microsoft has confirmed that code analysis is absent by design in Team Architect but that Visual Studio should not throw exceptions when building a project with code analysis enabled. I also reported this issue in the MSDN Product Feedback Center.]

I just watched the last part of the live webcast from the Visual Studio 2005 Launch Event in San Francisco. Steve Ballmer introduced Brian Goldfarb who in turn introduced a student who showed off the Club Web Site Starter Kit for ASP.NET 2.0. Microsoft's own code analysis tool wasn't very impressed with the Personal Web Site Starter Kit. Maybe, this one would do better.

On the ASP.NET website I found the download location for the Club Web Site Starter Kit. The download link send me a .vsi file. Opening the file gave me a short wizard to add a new web site template to Visual Studio 2005 (for both C# and VB.NET). I created a new web site using the new template. This web application compiled without errors. So far so good. 

But running code analysis on the C# gave a horrific number of 190 warnings.

Then I tried to run the site. No luck there, since SQL Server 2005 Express Edition refused to attach to the clubsite.mdf database that ships in the App_Data folder. The error was:

"Database 'P:\DOCUMENTS AND SETTINGS\ERWYN\MY DOCUMENTS\VISUAL STUDIO 2005\WEBSITES\CLUB WEB SITE STARTER KIT\APP_DATA\CLUBSITE.MDF' cannot be upgraded because its non-release version (600) is not supported by this version of SQL Server. You cannot open a database that is incompatible with this version of sqlservr.exe. You must re-create the database."

Poor timing on Microsoft's part: If you hype a starter kit at the launch event, you better make available a version that runs on the RTM version of SQL Server 2005! It's not as if Microsoft didn't know about this problem far in advance. A couple of ASP.NET forum posts show that people have been jumping through hoops since September 26, 2005 to get the database to work on the Release Candidate.

Here are the steps to follow to get the starter kit working if you have both SQL Server 2005 Developer and Express Edition installed:
  • Download the SQL script (packaged as an executable) that can create the tables and stored procedures.
  • In the SQL Server Management Studio connect to a Developer Edition or Express Edition instance and create a new empty database named clubsite.
  • Open the SQL Script in SQL Server Management Studio and run it against the clubsite database.
  • Detach the database by rightclicking on the database node, choosing Tasks | Detach.
  • Move the clubsite.mdf over the App_Data folder of the ASP.NET web application.
  • Run the web application.
[Update 2006-01-26: Microsoft has posted a new version of the Club Web Site Starter Kit that runs without modification on the RTM version of SQL Server Express. You can download it from here. It was digitally signed by Microsoft on January 12, 2006.]
Does SQL Server 2005 Express Edition support features that are not supported by other editions, like Developer Edition?

I didn't know, but I ran into a problem today while trying out the Personal Web Site Starter Kit. In the web.config it had this connection string:

<add name="LocalSqlServer" connectionString="Data Source=.\SQLExpress;Integrated Security=True;User Instance=True;AttachDBFilename=|DataDirectory|aspnetdb.mdf" />

Since my SQL Server 2005 Developer Edition instance is named SQL2005 I changed this to:

<add name="LocalSqlServer" connectionString="Data Source=.\SQL2005;Integrated Security=True;User Instance=True;AttachDBFilename=|DataDirectory|aspnetdb.mdf" />

When trying to run the ASP.NET application, I got this exception:

[SqlException (0x80131904): The user instance login flag is not supported on this version of SQL Server. The connection will be closed.]

Googling for information gave me an answer in a forum by Scott Forsyth:

"The issue is that User Instancing, which allows the automatic creation of databases from code, isn't support on the full version of SQL 2005.  That is a function of SQL Express only.  The solution is to manually create the database in SQL Server 2005 and set a connection string to point to it.  You will also need to run aspnet_regsql.exe manually against the database if you will be using any of the new built-in database features of ASP.NET v2.0."

So I had to install Express Edition to get the application to work. It also means, the answer to the question in the first line is YES.

After the installation I had three instances of SQL Server running:
  • SQL Server 2000 Standard Edition
  • SQL Server 2005 Developer Edition
  • SQL Server 2005 Express Edition
These showed up in Process Explorer as three separate processes all running a version of sqlservr.exe. A little investigation, that involved comparing the digital signatures, showed that 2005 Developer and Express Edition have identical binaries for sqlservr.exe even though both are installed in a separate location. What was different is that the Developer instance was running under the local SYSTEM account whilst the Express instance was running under the local NETWORK SERVICE account.

Something interesting happened when I started the web application when connected to the Express Edition. A new sqlservr.exe process was fired up. This time running under the interactively logged-on account named Erwyn. When looking at the open handles I saw it had opened the master database in the Application Data directory for that user: P:\Documents and Settings\Erwyn\Local Settings\Application Data\Microsoft\Microsoft SQL Server Data\SQLEXPRESS\master.mdf. This explains what the User Instance=True part in the connection string does. I think it is supposed to increase security in a shared hosting environment to allow lower priviliged accounts to dynamically attach databases. In my case this dynamically created SQL Server instance actually got more rights than the normal one, because the Erwyn account has more rights than the NETWORK SERVICE account on my computer. This happened because the web application was running in the ASP.NET Development Server. This process runs under my interactively logged-on account and not under the ASPNET account. So I configured the ASP.NET application to run in IIS 5.1. When connecting to the application, another sqlservr.exe process was started. This process ran under the low-privileged ASPNET account.

Something I noticed is that the user instances of SQL Server Express did not spin down automatically when no longer in use. Also the user instances kept running when I restarted the SQL Server Express service.

The connection to the user instance from the process running the data-access code (aspnet_wp.exe or WebDev.WebServer.exe) is done using named pipes. Something like \Device\NamedPipe\61A9EC07-5FDC-45\tsql\query.

The next thing I tried was to get Developer Edition to spin up a user instance. I copied the command-line parameters for a user instance spun up by Express Edition and changed the path to the Developer Edition binary. So I ran this from the command line:

"C:\Program Files\Microsoft SQL Server\MSSQL.2\MSSQL\Binn\sqlservr.exe" -U"C:\Program Files\Microsoft SQL Server\MSSQL.3\MSSQL\Template Data" -d"P:\Documents and Settings\Erwyn\Local Settings\Application Data\Microsoft\Microsoft SQL Server Data\SQLEXPRESS"\master.mdf -l"P:\Documents and Settings\Erwyn\Local Settings\Application Data\Microsoft\Microsoft SQL Server Data\SQLEXPRESS"\mastlog.ldf -e"P:\Documents and Settings\Erwyn\Local Settings\Application Data\Microsoft\Microsoft SQL Server Data\SQLEXPRESS"\error.log -c -SSQLEXPRESS -s61A9EC07-5FDC-45 -w60

Notice how the value of the -s parameter is the name of the named pipe. This worked just fine. WebDev.WebServer.exe had troubles connecting to the broken named pipe, but the user instance was up-and-running.

So this still begged the question: what is the hidden flag to let Developer Edition refuse to start a user instance when asked to in the connection string. Remember, its binary is identical to that of SQL Server Express.

So I manually created a new service for the Developer Edition binary and started it:

sc create testsvc binpath= "\"C:\Program Files\Microsoft SQL Server\MSSQL.2\MSSQL\Binn\sqlservr.exe\" -sSQLEXPRESS" type= own type= interact
net start testsvc

This indeed gave me an Express Edition-like instance capable of starting user instances. The key is the -sSQLEXPRESS command line argument. This tells SQL Server to use the SQLEXPRESS settings tree in the registry. Something in there tells sqlservr.exe how it should act.

Next I cloned the registry settings for the SQLEXPRESS instance to SQLEXPRESS2 and created another service for it. This amounts to manually creating another SQL Server instance. I also changed all the paths in that part of the registry to point to the Developer Edition installation. After changing the connection string in the ASP.NET application to SQLEXPRESS2, I connected to another Express Edition like instance, capable of starting user instances.

After some further experimentation I nailed it down to exactly one registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL.x\Setup\checksum. Toggling its (binary) value between the Express Edition and Developer Edition values enables and disables the user instance feature for a Developer Edition installation.

The conclusion is: there is absolutely no technical reason why Developer Edition cannot support creating user instances, yet the Developer Edition refuses ;(

BTW: If you wonder what the point of all this is. I dunno. I was just inspired by Mark Russinovich's search that revealed the Sony Music Rootkit to go hunting on my machine.
While playing with the Code Analysis in Visual Studio 2005 Team System I decided to try it out on some of the sample apps shipped by Microsoft. My first victim was the Personal Web Site Starter Kit. This sample app is shipped in all Visual Studio 2005 editions including the Professional Edition.

This app can be created by choosing the menu-item File | New | Web Site and selecting the appropriate web site template. Choose C# as the language. After the solution is created right-click the web site in the Solution Explorer and choose the Run Code Analysis on Web Site context menu-item. Be prepared for a list of 48 warnings!

Of course not all warnings indicate serious errors but I think it indicates some sloppy coding and a lot of errors can be fixed very easily. I am sad that Microsoft still ships such sample apps that set a bad example to developers by violating Microsoft's own coding guidelines.

One of the most silliest coding mistakes is the signature of these two methods (from the same class PhotoManager):

public static Stream GetFirstPhoto(int albumid, PhotoSize size)

public static void EditAlbum(string Caption, bool IsPublic, int AlbumID)

Could this sample app have been produced by a VB developer who is not aware of the casing guidelines for method parameters?!  So I checked out the VB version as well. It suffers from the same problems. Strangely enough the code analysis now gives 54 warnings.

Jan Schreuder has blogged on BloggingAbout.NET before about cyclomatic complexity. Go read it if you don't know the importance of keeping the cyclomatic complexity of methods reasonably low. Jan mentioned the tool DevMetrics to check it. I used C# Refactory in the past for calculating metrics.

Code analysis in Visual Studio 2005 Team System now includes a rule to enfore this as well. The rule is CA1502: Avoid Excessive complexity and can be found in the Maintainability Rules category. The VS2005 documentation states this about the rule:

Cyclomatic complexity measures the number of linearly independent paths through the method, which is determined by the number and complexity of conditional branches. A low cyclomatic complexity generally indicates a method that is easy to understand, test, and maintain. The cyclomatic complexity is calculated from a control flow graph of the method and is given as

cyclomatic complexity = the number of edges - the number of nodes + 1

where a node represents a logic branch point and an edge represents a line between nodes.

The rule reports a violation when the cyclomatic complexity is greater than 25. The following cyclomatic complexity thresholds determine the Message Level associated with the violation:

25 < Warning
50 < Critical Warning
75 < Error
100 < Critical Error

I think 25 is too high a value before giving a warning. Unfortunately these limits are set in stone in VS2005 and cannot be changed. The values given here seem more reasonable to me:

Cyclomatic Complexity Risk Evaluation
1-10 a simple program, without much risk
11-20 more complex, moderate risk
21-50 complex, high risk program
greater than 50 untestable program (very high risk)
Please read part 1 first. In that post I suggested to add a code analysis check-in policy to Team System with no rules selected if you only want to enfore a clean build policy. This is necessary because the separate clean build check-in policy has disappeared from Team System after Beta 2.

To comply with the code analysis check-in policies set on a Team Project, the code analysis settings on the Visual Studio project within a solution must be set to be at least as strict. I.e., stricter is fine, but more relaxed is not. This is a screenshot of the settings for a project:

Screenshot of the Code Analysis Settings for a project (click for larger version)

You can merge the settings from a Team Project over on to a Visual Studio project through the menu item File | Source Control | Migrate Code Analysis Policy Settings to Solution. This adds the rules in the Team Project Policy that have not already been set on the Visual Studio projects within the current solution. It leaves additional rules set on the projects in place.

As it turns out, it is okay to have not any rule set on the Team Project code analysis check-in policy. But Visual Studio will give you a CA0051 No rules were selected compilation error when you do the same on a project:

Screenshot of CA0051 No rules were selected error in Visual Studio 2005 (click for more details)

Nevertheless if the build was succesful, Visual Studio remembers this and you can check-in your code without any problems.

To get rid of the non-fatal "compilation" error you have to select at least one rule, like in the screenshot above, to stop Visual Studio from complaining.




The clean build policy is indeed gone from Team Foundation Server Beta 3.

If you only want to enfore that a project builds without errors before you can check-in one or more of its files, you must now use the code analysis check-in policy.

You can add a code analysis check-in policy through the menu item Team | Team Project Settings | Source Control. Go to the tab Check-in Policy and click the Add button. Select Code Analysis and click OK. Now the Code Analysis Policy Editor appears. You can deselect all of the code analysis rules and Visual Studio will still check for a succesfull build before allowing a check-in, like so:

 Screenshot of the Code Analysis Policy Editor of Visual Studio 2005 Team System (click for larger version)

Here is a screenshot of the policy violation on check-in that occurs when a project has not been build succesfully:

Screenshot of a Team System window showing a code analysis check-in policy violation when the project was not build succesfully (click for larger version)

<rant>

Checkout Windows Live in Firefox. Go read the comments about it on Robert Scoble's blog. Go read Joel on Software about it.

This is indeed a PR disaster. Announcing something web based at this day and age with Firefox support as an afterthought is pretty stupid.

And it is another branding disaster. I disliked the Windows Media Audio and Video branding. I dislike the Windows Blah Foundation branding. And now I dislike the Windows Live branding. Why? Because it sends a confusing message. Is WMA and WMV only supposed to be available on the Windows platform? This seamed to be the case for Windows Presentation Foundation, so I thought I could live with it. But then at PDC05 Microsoft announced Windows Presentation Foundation Everywhere (WPF/E). If it is supposed to be available everywhere, why brand it with Windows?!

.NET suffered from serious branding misuse in the past. Remember every MS server product getting the .NET label stuck on it, even if it had almost nothing to do with the .NET Framework. Since then Microsoft has backed off from using .NET in product names. Did you notice it has even disappeared from the Visual Studio product name: it's Visual Studio 2005 and not Visual Studio .NET 2005.

Maybe Microsoft should completely drop the Windows term for the next version of its OS and just call it Vista.

</rant>

I like installing the latest and greatest software. One thing missing from the Visual Studio 2005 puzzle was Team Foundation Server Beta 3 Refresh (TFS).  

At home I have two computers available that both run Windows XP Professional. Both have 1 GB RAM. TFS only runs on Windows Server 2003 SP1. Because I want TFS to be portable for demo purposes I decided to install it in a virtual machine on my laptop.

 So I dug up a pre-existing clean Windows Server 2003 Virtual PC image, copied it over to my laptop, and installed the following things on it:

  • Windows Server 2003 SP1
  • All post-SP1 security updates
  • SQL Server 2005 Developer Edition (*)
  • SharePoint Services 2.0 with SP2
  • VS 2005 Team Foundation Server Beta 3 Refresh
  • VS 2005 Team Foundation Client Beta 3 Refresh

At home I don’t run an Active Directory, so I decided to try out TFS in Workgroup mode. I got two warnings from the SQL Server 2005 and the TFS prerequisite checkers, but those were to be expected. I could only allocate 700 MB for the VPC and that it is a tad too little for those two products. Everything installed without problems. The only thing I noticed is that TFS Setup suffers from the Microsoft Progress Bar Syndrome: the progress bar progresses steadily but hangs for minutes at the 99% mark.

 

Installing Team Foundation Client on the server gives you the Team Explorer in an otherwise empty Visual Studio 2005 Standard Edition IDE:

Screenshot of the about box for Team Explorer installed in otherwise empty Visual Studio 2005 IDE on a Team Foundation Server (click for larger version)

Since I had already installed Visual Studio 2005 Team Suite with the Team Foundation Client, the next step was connecting to TFS. This worked without any login boxes, because I had configured local accounts with the same username and password on both the client and the server. This account is a local administrator on the server, and as such is automatically a member of the Team Foundation Administrators.

After connecting I created a new Team Project. This is the result:

 

My first Team Project in Team Foundation Server Beta 3 Refresh (click for larger version)

Thank you Microsoft for a job well done. Installing TFS is a breeze.

 

 (*) Don’t forget to configure remote connections it if you choose this edition.

More Posts Next page »