Monthly Archives: November 2005

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.NETFrameworkv2.0.50727CONFIGBrowsers. 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.

1 Comment

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.]

1 Comment

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 FilesMSBuildMicrosoftVisualStudiov8.0CodeAnalysisFxCopTask.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.]

1 Comment

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 SETTINGSERWYNMY DOCUMENTSVISUAL STUDIO 2005WEBSITESCLUB WEB SITE STARTER KITAPP_DATACLUBSITE.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.]

1 Comment

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 SettingsErwynLocal SettingsApplication DataMicrosoftMicrosoft SQL Server DataSQLEXPRESSmaster.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 DeviceNamedPipe61A9EC07-5FDC-45tsqlquery.

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 FilesMicrosoft SQL ServerMSSQL.2MSSQLBinnsqlservr.exe" -U"C:Program FilesMicrosoft SQL ServerMSSQL.3MSSQLTemplate Data" -d"P:Documents and SettingsErwynLocal SettingsApplication DataMicrosoftMicrosoft SQL Server DataSQLEXPRESS"master.mdf -l"P:Documents and SettingsErwynLocal SettingsApplication DataMicrosoftMicrosoft SQL Server DataSQLEXPRESS"mastlog.ldf -e"P:Documents and SettingsErwynLocal SettingsApplication DataMicrosoftMicrosoft SQL Server DataSQLEXPRESS"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 FilesMicrosoft SQL ServerMSSQL.2MSSQLBinnsqlservr.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_MACHINESOFTWAREMicrosoftMicrosoft SQL ServerMSSQL.xSetupchecksum. 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.

1 Comment

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.