How to silently uninstall .NET Framework hotfixes

I heard from a customer recently who had run into the scenario described in this previous blog post - the .NET Framework 1.1 SP1 would not install because a previous hotfix was installed that blocked SP1 setup from running. In most cases, it is relatively simple to go to Add/Remove Programs and uninstall the .NET Framework hotfix, and then install the service pack. However, the customer who contacted me needed to automate removing this hotfix on multiple computers.

He tried looking at the UninstallString value in HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\M886904, and it listed the following:

"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Updates\hotfix.exe" "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Updates\M886904\M886904Uninstall.msp"

However, running this command line will generate a dialog asking the user to confirm that they really want to remove the hotfix. This makes it unfriendly for automated uninstallation on multiple machines. To complicate things, running this copy of hotfix.exe with a /? or /h to try to figure out the allowable command line parameters did not show a usage dialog. Also, despite the executable being named hotfix.exe, it did not accept the command line parameters described in this knowledge base article.

I knew that this version of hotfix.exe was not the same as the one listed in the knowledge base article, but I was unable to find any additional information about it on my own. I ended up asking Heath Stewart, a developer on the servicing team for Visual Studio and the .NET Framework. He provided the following information about why this version of hotfix.exe is needed and what command line parameters it allows.

.NET Framework hotfix command line parameters

The general format for the command line to run the .NET Framework hotfix.exe is the following:

Hotfix.exe [/q] <path to patch MSP> [arguments to pass to szCommandLine in the MsiApplyPatch API]

The /q parameter and the arguments parameter are optional. The patch MSP should be located in %windir%\Microsoft.NET\Framework\v#.#.####\Updates\M######\M######Uninstall.msp. The easiest way to run a .NET Framework hotfix uninstall in silent mode is to locate the UninstallString for this hotfix in HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\M######, copy it and add /q before the path to the MSP.

What does this version of hotfix.exe do?

The patch MSP that is located in %windir%\Microsoft.NET\Framework\v#.#.####\Updates\M######\M######Uninstall.msp is generated during the installation of the hotfix. It is an "anti-patch" that is applied by hotfix.instead of performing a direct uninstall of the patch. Uninstalling these patches directly is not supported because they do not have the MsiPatchMetadata table (which determines if the patch can be uninstalled or not) or the AllowRemoval property that must exist in that table. The MsiPatchMetadata table is only supported in Windows Installer 3.0 and later, and the .NET Framework 1.0 and 1.1 require Windows Installer 2.0 for installing and uninstalling and therefore must also support patching using Windows Installer 2.0.

Important note about .NET Framework service packs

The information listed above only applies to .NET Framework hotfixes that create their own Add/Remove Programs entries. .NET Framework service packs are not uninstallable on their own. You have to uninstall the .NET Framework itself, which will uninstall the base .NET Framework and the service pack in a single step.