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 C