0
votes

On a Windows Server 2012 machine, an msi file has installed the assembly ABCD.dll into the GAC_32. I try to patch this file with WindowsPowerShell, with the following commands:

[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")            
$publish = New-Object System.EnterpriseServices.Internal.Publish            
$publish.GacRemove("C:\Windows\Microsoft.NET\assembly\GAC_32\ABCD\v4.0_1.0.0.0__8a93b7fd09f0e7e7\ABCD.dll")      
$publish.GacInstall("C:\Patch1\ABCD.dll")

However the GacRemove command fails. In the Windows Event Log/Application I get the following message:

Removal of an assembly from the global assembly cache failed: C:\Windows\Microsoft.NET\assembly\GAC_32\ABCD\v4.0_1.0.0.0__8a93b7fd09f0e7e7\ABCD.dll ABCD,Version=1.0.0.0

Does somebody have an idea, what could be the reason?

I tried as well the 32 bit (C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe) as well the 64 bit (C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe) WindowsPowershell in administrator mode.

gacutil does not work either. I try the following:

"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\NETFX 4.0 Tools\gacutil" -u ABCD.dll

and get the following message:

Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.30319.1
Copyright (c) Microsoft Corporation.  All rights reserved.
No assemblies found matching: ABCD.dll
Number of assemblies uninstalled = 0
Number of failures = 0

However when I get the list of the assemblies with

"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\NETFX 4.0 Tools\gacutil" -l

I see the following line:

ABCD, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8a93b7fd09f0e7e7, processorArchitecture=x86
1

1 Answers

0
votes

As mentioned in the article "Microsoft Installer does not remove assemblies from the GAC - Global Assembly Cache Pin" the problem is that the registry key in HKEY_CLASSES_ROOT\Installer\Assemblies\Global\[Assembly full name] has a value, which was set, when the assembly was installed by the msi. Therefore, to patch the assembly, the registry value has to be cleared, the assembly has to be uninstalled, the patched assembly has to be installed, and the registry value has to be set to the old value. The registry value could be left empty, but then upon uninstalling the msi, the registry key is not deleted. Therefore, it is best to set the registry value again to the old value. I finally wrote the following VB.NET Code to patch the assembly:

        Dim subkey = My.Computer.Registry.ClassesRoot.OpenSubKey("Installer\Assemblies\Global", True)
        Dim keyname = "ABCD,Version=""1.0.0.0"",Culture=""neutral"",ProcessorArchitecture=""MSIL"",PublicKeyToken=""8A93B7FD09F0E7E7"""
        Dim values As String() = subkey.GetValue(keyname)
        subkey.SetValue(keyname, {""})
        Dim assemblyname =
            "C:\Windows\Microsoft.NET\assembly\GAC_32\ABCD\v4.0_1.0.0.0__8a93b7fd09f0e7e7\ABCD.dll"
        Dim p = New System.EnterpriseServices.Internal.Publish()
        p.GacRemove(assemblyname)
        p.GacInstall("D:\Patch1\ABCD.dll")
        subkey.SetValue(keyname, values)

In the above code, ABCD has to be changed to the right assembly name, and 8a93b7fd09f0e7e7 to the public key token of the assembly.