Thoughts about setup and deployment issues, WiX, XNA, the .NET Framework and Visual Studio
All postings are provided AS IS
with no warranties, and confer no rights. Additionally, views expressed
herein are my own and not those of my employer, Microsoft.
A few months ago I posted a blog article about how to chain the unattended installations of the Visual Studio prerequisites, Visual Studio and MSDN. In the past few weeks I have been helping a customer who contacted me with some follow-up questions because they wanted to perform a full install of MSDN instead of a default install. What the customer found was that in a normal scenario where they installed MSDN via a command line it was possible to perform a full install with the following command line:
<path to MSDN setup.exe> ADDLOCAL=ALL /qn
However, they found that using the instructions in my blog post was not working when they included the ADDLOCAL=ALL part of this command line. After several back and forth email iterations and trying different types of scenarios, we finally figured out that the exact command line that had to be listed in the [PostSetupLaunchList] of the unattended INI file for an MSDN full install has to read:
<path to MSDN setup.exe> "ADDLOCAL=ALL" /qn
Note the quotes around the ADDLOCAL=ALL part of this command line. I spent some time looking through the code that processes these unattended command lines and found that it was cutting off the part of the string after the equal sign unless the equal sign is enclosed in quotes. There is some legacy code deep in this setup infrastructure that is attempting to parse some of the contents of the unattended INI file using <name> = <value> syntax. In this case, the commands should just be a list of commands, one per line, so that type of name/value parsing is a bug that we just happened to not find until now.
So, after a lot of iterations the customer was able to implement their scenario, including unattended full install of MSDN. Hopefully this information will be useful to anyone else trying something similar in the future...
The official website for the Mobile and Embedded Developer's Conference (MEDC) 2005 is now available and being populated with new information all the time. A few of you have asked me about whether or not there will be conferences in other parts of the world and I am happy to say yes. Check out this site to see where and when. You can also see a session list along with brief descriptions here.
I hope you all will be able to attend this year!
I was working with a couple of different customers today who saw a .NET Framework initialization error dialog that says that setup failed to load mscorwks.dll appear when trying to install ASP.NET hotfix KB886903. The exact error dialog looks like this.
It turns out this is being caused by a race condition that can happen when trying to install one .NET Framework or ASP.NET hotfix immediately after installing another .NET Framework or ASP.NET hotfix. There is special logic in the .NET Framework hotfix and service pack setup wrapper that is used to rerun ngen.exe to regenerate native images for some of the .NET Framework binaries. This process is done when installing the .NET Framework, but the native images are invalidated by any changes made to them (such as when they are patched by a service pack). The process that reruns ngen.exe is separate from the original hotfix installation and in some cases it is scheduled to occur after the next reboot (to account for files in use and things like that).
In both of the scenarios I saw, the customers had installed .NET Framework 1.1 SP1 via Windows Update and then were required to reboot. After the reboot, the background process was launched by an entry in the RunOnce registry hive and at approximately the same time the setup for the ASP.NET hotfix was launched by Windows Update or Automatic Update. In some cases, these two processes try to access some of the same resources at the same time and it ends up resulting in an error message.
The end result of this error message is that one or more of the native images fails to be recreated. This does not cause the .NET Framework to fail in any way, but since ngen.exe is designed to improve performance for the binaries in question, it can lead to performance degradation for the .NET Framework.
If you hit this error and want to make sure that the files will have correct native images generated for them by ngen.exe you can reapply the service pack to cause these commands to be rerun.
I found a really useful tip article that Sean Liming wrote about configuring a system to dual-boot a desktop Windows OS and Windows XP Embedded (for testing and possibly deployment purposes). You can find the tip article here and other useful information on his main site.
For those of you who don't know him, Sean is a Windows XP Embedded MVP and he also wrote the extremely useful book Windows XP Embedded Advanced (which I highly recommend by the way - in fact, when I joined the Windows Embedded team at Microsoft, this book was the first one given to me by my manager to ramp up on our team's features).
I got a question from a customer this week who could not get an ASP.NET hotfix installed by launching it from Windows Update (due to an error like some folks have seen with other .NET Framework service packs that I described here). As a result, he was trying to download the package directly, extract it and install manually, but he was having trouble trying to locate the underlying package and download it. So I decided to try to do this myself to see how the process really works for an IT admin in the field, and I'm surprised by how complicated this process is. Here are the specific steps I had to follow to locate and download this ASP.NET hotfix:
It really seems like there should be an easier way to locate, download and extract a hotfix package from Microsoft. If there is a simpler way that I have missed, please post a comment and let me know.
As a side note, this and any other .NET Framework or ASP.NET hotfixes are packaged using the same self-extracting wrapper as the .NET Framework 1.0 SP3 and 1.1 SP1, and therefore are all susceptible to the same set of issues as those service packs. There is one big issue (that I consider to be a flaw) in the design for the packaging of the .NET Framework service packs and hotfixes. The self-extracting wrapper EXE is written in managed code, so that means that if the .NET Framework is broken in any way and needs to be repaired, then the patch package will not even extract and launch correctly, and it cannot even give a useful error message.
I was on a mail thread this week about a bug in the .NET Framework 1.1. There was a logic problem within Fusion that causes assemblies in the GAC to not be updated by Windows Installer if an assembly with the same assembly version but different file version is already present and if the string length of the file version is greater than the string length of the assembly version.
Our setup team found an instance of this problem immediately before shipping the .NET Framework 1.1 and Visual Studio .NET 2003 in this scenario: some internal customers had an RC (release candidate) version of the .NET Framework 1.1 and Visual Studio .NET 2003 installed, then uninstalled them in order to install the final build. Some folks uninstalled the .NET Framework 1.1 first, and if they had no other version of the .NET Framework on their machine there was no longer any version of fusion on the machine so uninstalling Visual Studio or the J# redistributable pack would leave behind assemblies in the GAC. When we attempted to validate the installation of the final build we found that some of the assemblies in the GAC were still the RC version.
At any rate, I found out this week that there was supposed to be a knowledge base article written for this issue but it ended up not being published, so I wanted to post the contents here. Note that this issue has been fixed in the .NET Framework 1.1 SP1 and in the upcoming version 2.0.
FileVersion attribute in assembly name table is not honored during install and uninstall of assemblies
There is a bug parsing the FileVersion=w.x.y.z attribute in the display name. Briefly, the parsing code takes a pointer to the attribute value and a size field. The size field passed in is the size of the assembly version rather than the file version. So, if the file version ends up being longer in length (string length) than the assembly version, we prematurely terminate parsing of the file version, and end up comparing the wrong file version. This could cause patches to not get installed when you think they should.
In the assembly name table, pad the Version field with leading zeros to workaround this problem. For example, if your assembly name is "Foo, Version=126.96.36.199, culture=neutral, publickeytoken=123456abcdef, FileVersion=1.0.3500.0" you would hit this problem since length of FileVersion field is longer than length of Version field. Modify assembly name to contain Version=00001.0.0.0 to workaround the problem.
Rob Mensching wrote a blog entry a while back that explains some reasons why you should not use script-based custom actions in your setup. I encourage you all to read it if you haven't yet, and I also strongly encourage you to heed his recommendations if at all possible.
I can personally relate to one of his explanations as well. Reason #3 on his list talks about anti-virus programs. When we shipped Visual Studio .NET 2002 we started getting reports of seemingly random failures during setup from our product support team. After some detailed analysis we found that many of these failures were being caused by overly aggressive anti-virus programs that were blocking scripts from running even as part of custom actions during VS setup. We scrubbed our custom actions before shipping Visual Studio .NET 2003 to re-write or eliminate the script-based custom actions to avoid these failures, and we were able to eliminate a fairly high support call generator.
Hey all, the doc I originally wrote about 1935 errors does not do a very good job of providing details about root causes of many of the possible HRESULT values that I list (thank you to Carolyn on the Windows Installer team for pointing this out). So, as I get some time, I'm going to try to go through the ones I know of and provide more detailed examples of when I've seen them happen in my experience. I wanted to start by linking to a really good overview that Alan Shi on the Fusion team wrote about a few of the HRESULTs that can possibly be returned by Fusion - check it out here.
<update date="1/15/2006"> Unfortunately, it appears that the link to Alan's list of Fusion error codes no longer works. I was able to find a knowledge base article describing the GAC APIs available in the .NET Framework, but I could not find a detailed reference to Fusion error codes. I will try to get a list put together and posted in the near future. </update>
I was helping investigate a .NET Framework installation failure last week that turned out to have an interesting root cause, so I wanted to pass along the information I learned. The .NET Framework was failing with a 1935 error, and the HRESULT value was 0x80070002. In general this HRESULT means "the system cannot find the file specified" - and since the .NET Framework is packaged up in a single self-extracting package, it is nearly impossible to get this particular HRESULT during setup.
One of the developers investigated a similar issue and found that this particular HRESULT can be caused by a certain type of adware running on the machine. If you launch Task Manager and then look at the Processes tab, take a look for a process named wtoolsa.exe. If this process is running, you will need to clean off this adware (for example by following the suggestions at this site).
One note - the machine that I looked at that was infected with this adware was pretty difficult to clean up. It relaunched itself when I killed the process, it replaced entries in the Run and RunOnce keys when I deleted them. I didn't get a chance to try all of the recommended steps in the article I linked to, but I'm guessing there are some more aggressive tactics you could take to rip it off your machine.
Hopefully this will help some of you solve installation issues for the .NET Framework and other products that fail with 1935 errors with HRESULT 0x80070002.