A frequently-asked question is how to install an assembly into the Global Assembly Cache (GAC) and overwrite the old assembly that has the same strong name. This is known as in-place updating.
The first answer is “don’t”. Besides being a trusted global store for managed assemblies that is intrinsic to assembly resolution, the GAC also provides side-by-side versioning. Multiple versions of a managed assembly can exist in the GAC at the same time and the Common Language Runtime (CLR) loads a version based on the manifest for a calling assembly, or the calling assembly can load an assembly by its strong name. Versions can be redirected using publisher policies as well, which direct the CLR to load a different version of an assembly when another version is requested. If an application should not be redirected to the newer assembly for any reason, it can include the <publisherPolicy apply="no"/>
element in its application configuration file.
It would seem hypocritical, however, to preach such a practice when Microsoft does in-place updates. Keep in mind that we are the framework – pun intended – on which other managed applications are typically built on Windows. Publisher policies installed into the GAC could get out of hand and applications that want to avoid redirection for their own assemblies in the GAC would also use older base class libraries in the GAC as well if the <publisherPolicy apply="no"/>
element was under the <assemblyBinding/>
element. There are also good reasons for anyone to use in-place updates: security fixes. You may not want an application to use an older assembly because it may contain a security hole that opens the entire machine up for attack. To mitigate such a threat you should either update the assembly in-place, or remove it and install a new assembly along with a publisher policy. Any applications avoiding redirection would break, of course, but that in most cases would be better than opening a security hole.
To configure your product installed using Windows Installer to update assemblies in-place, you need to add or update your MsiAssemblyName
table to include a FileVersion property with the new file version – not the assembly version, which must remain the same to update the old assembly in-place – of the assembly. Consider, for example, updating managed assembly Foo.dll with assembly version 1.0.0.0 and file version now 1.0.100.0:
Component_ | Feature_ | File_Manifest | File_Application | Attributes |
C_FOO_DLL_GAC | DefaultFeature | FOO_DLL_GAC | 0 |
Component_ | Name | Value |
C_FOO_DLL_GAC | Name | Foo |
C_FOO_DLL_GAC | Version | 1.0.0.0 |
C_FOO_DLL_GAC | Culture | neutral |
C_FOO_DLL_GAC | PublicKeyToken | 0123456789abcdef |
C_FOO_DLL_GAC | FileVersion | 1.0.100.0 |
With no data in the File_Application
column of the MsiAssembly
table, the assembly will be installed into the GAC. With a different FileVersion property value, MSI will cause Fusion to overwrite the old assembly with the same strong name with the new one. In order for this to work, however, it’s important to note that .NET Framework 1.1 or higher must be installed so that the correct version of Fusion is on the system. For more information, read “Updating Assemblies” in the Windows Installer SDK.
0 comments