Why can't I uninstall my assembly?

When installing an assembly to the GAC, Fusion provides a mechanism for the installer to specify a traced reference count on the assembly being installed. The idea is that if the same assembly is installed multiple times by different clients, the assembly is not removed until all of the clients that installed the assembly have explicitly requested uninstall. Without such a feature, you could run into scenarios where assemblies are prematurely uninstalled. For example: two applications install the same shared assembly to the GAC; one application is uninstalled, and the shared assembly is removed even though another app still needs it.

The reference counts Fusion provides are called “traced” reference counts, because unlike COM reference counts, which simply record the number of outstanding clients, an installer is allowed to specify information identifying who needs the particular assembly. There are different kinds of traced reference counts that an installer can provide, such as a filepath, or an opaque string that is installer-specified. Gacutil allows you to specify traced reference counts in an install command-line via the /r option.

You can read more about traced reference counts in this gacutil MSDN document. There is also information about traced reference count in our support article describing the unmanaged Fusion API.

When you install your assembly using MSI (which is the recommended approach for retail installs), there is no need to specify a traced reference count for your assembly, because MSI has its own internal reference counting mechanism. When Fusion is asked to uninstall an assembly from the GAC, it will check if there are any outstanding traced reference counts. If there aren't any traced reference counts, Fusion will call a Windows Installer API to determine whether or not MSI holds a reference on the assembly. If any reference count (traced reference count, or MSI reference count) exists, the assembly will not be uninstalled.

If you try to uninstall an assembly in the GAC using “gacutil -u”, you may see a message indicating that some traced reference count remains on the assembly, and gacutil will output the information about the pending traced reference count. In order to uninstall it, you must remove all the traced reference counts. For MSI-installed assemblies, this is only possible by uninstalling the MSI package that installed the assembly via Add/Remove programs.

Some customers have reported unusual cases where an assembly installed into the GAC via gacutil without a traced reference count, can later not be uninstalled via “gacutil -u“. When the uninstall is attempted, the following message appears:

Unable to uninstall: assembly is required by one or more applications Pending references:

SCHEME: <WINDOWS_INSTALLER> ID: <MSI> DESCRIPTION:<Windows Installer>

This message is informing the user that Fusion thinks that Windows Installer holds a reference count on the assembly, yet this information is clearly wrong because the assembly was never installed via MSI.

If you encounter this problem, it is very likely that you have run into an odd MSI registry corruption (at the time of this writing, the cause is unknown). Without getting into a long-winded explanation of how this registry corruption eventually results in the error message above, the common cause of this is a bogus default value set under one (or both) of the below registry keys:

[HKCU\Software\Microsoft\Installer\Assemblies\Global]   

[HKLM\SOFTWARE\Classes\Installer\Assemblies\Global]

If these keys are not empty (e.g. they contain a MSI descriptor value), then you have hit this situation, and you should be able to fix the problem by clearing the default value. I can't guarantee that this will always work, but it has definitely been our experience that this is the most common source of this problem.

(This tip comes courtesy of our resident MSI expert on the Fusion team, Roberto Sciore).