.NET Fusion
Home About Workshops Articles Writing Talks Books Contact

6. Publisher Policy Files

In the previous examples an application is told to use a new version of a library through the application configuration file. If the library is a shared library it could be used by many applications, so this mechanism would require an administrator to install the new library and then search the hard disk for all the applications that use the library and edit their configuration files. This could involve editing lots of files, and the administrator may not find all of the applications. This problem is solved using publisher policy files.

I have to reiterate that configuration files are associated with process assemblies, however, publisher policy files are associated with libraries but still have the same format as configuration files.

It is worth pointing out at this point that you should use publisher policy files sparingly. The classic situation for a publisher policy is if your library has a security fault and you want to publish a new library that adds no features but fixes the security fault. Your overriding reason to deploy the new version of the library is to ensure that the existing applications will be fixed. Using a publisher policy file means that you do not need to change the existing applications.

A situation where a publisher policy file is not a good idea is when you change the library to add new features. This is likely to lead to an incompatibility nightmare because you will not be able to test that all the old versions of the applications that use the shared library will work with the new version. In this case it is far better to build new versions of the applications against the new version of the library.

If you have any doubt about using a publisher policy file then the best course of action is to avoid publisher policy files and instead create new versions of the applications that use the new version of the library. 

6.1 Creating a Publisher Policy

In this example you will create version 1.0.0.0 of the library that you used on previous pages and the process that uses the library. The library has a strong name (provided through a key file) and install the library into the GAC. Then you'll create another version of the library and install that (and the publisher policy file) into the GAC so that the new version of the assembly is loaded by the runtime without having to change the process configuration.

The first thing is to check that lib.cs has a version of 1.0.0.0 and then compile the library and the process. Next install the library into the GAC and delete the local copy. Ensure that the application does not have a configuration file (delete it if there is one). Now run the process and confirm that Fusion picks up the GAC copy of the library. Now edit the library code so that the version is 1.1.0.0 and compile just the library. Add this version of lib.dll to the GAC and delete the assembly from the local folder.

You will now create the publisher policy file. This is an assembly with a resource file that has binding information. You cannot use the configuration file to create this file. Instead, you must write this file by hand (although there are some short cuts as I'll mention in a moment). You need a text file that has the following information, you will create this file in a moment.

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="lib"
          publicKeyToken="ede6789fb0b13219"/>
        <bindingRedirect oldVersion="1.0.0.0"
          newVersion="1.1.0.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Note that this has the same format as an application configuration file. Thus, the easiest way of creating this file is to use the configuration tool to create the process configuration file and then rename the file. Use the configuration tool to configure the lib library to redirect version 1.0.0.0 to version 1.1.0.0. (see Example 3.6) Close the configuration tool and rename the process configuration file app.exe.config to lib.config.

Next, you have to make a resource-only assembly with this file. To do this type the following at the command line:

al /out:policy.1.0.lib.dll /version:1.0.0.0
   /keyfile:key.snk /linkresource:lib.config

( indicates a new line added for formatting in this document). This needs more explanation. al.exe is the assembly linker tool. With these switches this tool will create a library assembly with a strong name and it is important that the key pair you use for the policy file is the same as the one that you use for the library. The policy is contained in the configuration file that you have already created, this must be linked to the policy assembly as a separate file, it should not be embedded. The policy file is a library assembly with a name in the form:

policy.<major>.<minor>.<assemblyName>.dll

Here, <major> and <minor> refer to the versions that are redirected in the policy file. Since we want to redirect 1.0.0.0 the policy file is named with a value for <major>.<minor> of 1.0. It is odd that the file has to have a name in this specific form, but you have no choice, if you don't follow this form Fusion will not use your policy file. Finally, the policy file itself can be versioned and Fusion will only use the latest version, here I version the policy file to 1.0.0.0, but note that this has nothing to do with the versions being redirected.

Finally add policy.1.0.lib.dll to the GAC and delete the local copy of the assembly (and lib.config) from the local folder. Run the process and confirm that the new version of the assembly is loaded. Notice that although the application manifest says that it will use version 1.0.0.0 and there is no process configuration file to redirect this binding, the application uses version 1.1.0.0. Remove the policy file (gacutil -u policy.1.0.lib) and run the process. This time the process will use version 1.0.0.0 from the GAC.

The advantage of a publisher policy file is that an administrator only has to install the policy file assembly and the new library into the GAC and does not have to worry about any of the assemblies that use the library. If the library changes again, all the publisher has to do is create a new version of the policy file and deploy that file and the new library. Indeed, the publisher may not even have to deploy the library because the configuration file can contain a <codeBase> element to indicate that the code should be downloaded from a web site on the intranet or internet.

One final point about the last example. When the policy file is installed into the GAC all of the assembly is installed. An assembly can be made up of several files, in this case the assembly is two files, the PE file policy.1.0.lib.dll and the resource file lib.config. Both of these files are installed into the GAC.

If the application fails to work after an assembly has been updated you can use the Fix an Application tool (but not for version 3.0/2.0 of the runtime) described earlier. Note that the SafeMode option will turn off the use of policy files, it does this by adding the following line to the <dependentAssembly> node in the application configuration file:

<publisherPolicy apply="no"/>

However, as I've noted earlier, publisher policy files are typically used for security fixes, so the opt out provided by this node allows the user to continue to run with the security problem. Since this is a security issue this opt out is controlled by a CAS permission, which is not enabled by default for partial-trust applications.

Before finishing this section clean up the files you have created. First, remove the two versions of the library from the GAC either by using the explorer namespace extension, or if you know that there are no other assemblies called lib you can use gacutil -u lib. Finally, if you have not done so already, remove the policy file from the GAC using explorer or gacutil -u policy.1.0.lib.

I hope that you enjoy this tutorial and value the knowledge that you will gain from it. I am always pleased to hear from people who use this tutorial (contact me). If you find this tutorial useful then please also email your comments to mvpga@microsoft.com.

Errata

If you see an error on this page, please contact me and I will fix the problem.

Page Seven

This page is (c) 2007 Richard Grimes, all rights reserved