Tuesday, January 27, 2009

How to fix Windows SDK Configuration Tool

There are many posts out there pointing out that Windows SDK Configuration Tool contains a bug. When I first met the issue I googled hither and thither but did find a solution for Visual Studio 2005. The workarounds did not work for me and were too clumsy to use them on a regular basis.

Eventually I decided to dig into its code - fortunately WindowsSdkVer.exe is a .net assembly. Therefore, bingo, we can use .net reflector to infer its sorce code. It wasn't too difficult. To that end, the reflector contains an option to export an entire assembly as the visual studio project:

 Export an assembly

The exported WindowsSdkVer project contained a dependency, the library VCIntegrate.dll, that can be found in the same folder as WindowsSdkVer.exe itself lies. I added the library to the project references and could build and run it.

Running the project on my Vista x64 I quickly found my issue. It was in the Utility.cs file, the GetInstalledProduct method:

foreach (string str in key.GetSubKeyNames())
{
    RegistryKey key2 = key.OpenSubKey(str);
    Product newProduct = new Product();
    try
    {
        newProduct.SdkVersion = str;
        if (!string.IsNullOrEmpty(productVersionKey))
        {
            newProduct.Version = new Version(key2.GetValue(productVersionKey).ToString());
            newProduct.Version = new Version(key2.GetValue(productVersionKey).ToString().Replace("v", "").Replace("A", ""));
        }
        else
        {

The problem is that the Version class can't parse version given as the value of v6.0A being in my windows registry under the following key: HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\Microsoft\Microsoft SDKs\Windows\v6.0A\ProductVersion.

Stripping leading and ending characters helped somehow. But the code seemed to contain various issues. The next one I met was in VersionSelector.cs, the GetInstalledVisualStudioVersions method:

foreach (Product product in products)
foreach (Product product in new List<Product>(products))
{
    float num;
    if (float.TryParse(product.SdkVersion, out num))
    {
        if (num < 8f)
        {
            products.Remove(product);
        }
    }
    else
    {
        products.Remove(product);
    }
}
return products;

Guess what a problem may raise up here? Who did write this?  You can't delete from a collection during looking it through by enumerator.

And at last for those having a non-english windows you have to add a line into the Program.cs file:


[STAThread]
private static void Main(string[] args)
{
    Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
 
    Mutex mutex = null;

It is required to parse numbers correctly.

You should place the compiled execution over the existing one to ensure that all its functionallity works properly. That because the program relies on files lying around.

If you somehow trust me, you can download the patched utility directly.