One of the common questions I get from customers who are trying to redistribute the .NET Framework with their setup package is how to handle reboots that might happen during .NET Framework setup. I'll try to address the various questions I've seen so far in this blog post.
When does .NET Framework setup require a reboot?
The .NET Framework setup will require a reboot when one of the files it needs to install is in use during installation. There are a handful of files that are shared by all versions of the .NET Framework, so if there is an earlier version of the .NET Framework installed on the system than the one that is currently being installed, and a managed application is running and holding one of the shared files in use, then a reboot could be required at the end of installation.
How can I tell if .NET Framework setup requires a reboot?
The .NET Framework setup will return code 3010 if it detects that a reboot is required in order to complete installation. It will return this code if .NET Framework setup is run in full UI mode, unattended mode or silent mode.
Can I defer the reboot if the .NET Framework setup returns code 3010?
In general, it is safe to defer a reboot required by the .NET Framework until the end of your setup process. This means you can install the .NET Framework and your application in a single setting and then reboot afterwards if the .NET Framework setup returned 3010. You can also install the .NET Framework and a .NET Framework hotfix and defer the reboots until after your product setup completes.
You should not defer the reboot indefinitely, however. You may see unpredictible behavior in your application if it is attempting to run on top of a version of the .NET Framework that needed a reboot at the end of setup and the reboot has not yet happened.
How can I force a reboot during .NET Framework setup to make sure my setup it will handle it correctly?
Because of some work done in the .NET Framework 2.0 setup, it can be difficult to create scenarios where .NET Framework setup returns error code 3010. However, it is necessary to create reboot scenarios in order to test the code paths in your setup program that are designed to handle these reboots.
The most reliable way I have found to test reboot scenarios is to do the following:
- Install an earlier version of the .NET Framework than the one you are including in your setup package. For example, if you are going to redistribute the .NET Framework 2.0, then install the .NET Framework 1.1 or 1.0.
- Use a tool to lock one of the files for writing that was installed to %windir%\system32 by the previous version of the .NET Framework installed in step 1. I have been using a tool written by a fellow Microsoft employee named lock.exe (you can download it here). This tool provides a graphical user interface that lets you specify the type of lock to place on a file. For this type of reboot testing, you can use the write lock (number 3 in the lock.exe UI).
- Run your setup and let it install the .NET Framework while the files are held in use by the tool from step 2. Verify that your setup handles the 3010 return code the way you intend it to.
Note - make sure to not use read/write locks (number 4 in the lock.exe UI) to test reboot scenarios. If you try to do that, you will receive an error message with the following text, and the only options are to retry or cancel.
Microsoft .NET Framework 2.0 Setup
Error 1306.Another application has exclusive access to the file 'C:\WINDOWS\system32\mscorier.dll'. Please shut down all other applications, then click Retry.
Unfortunately, you cannot ignore this error and have setup continue. If you try to force one of the .NET Framework shared files to be in use by opening the DLL in Microsoft Word, you will see this error as well because it opens the file for read/write access.
Hopefully this post has addressed any questions you might have about how to handle reboots during .NET Framework setup in redistribution scenarios. Please let me know if you see anything that I've missed....
<update date="7/23/2009"> Fixed broken link to lock.exe. </update>