<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Alan Shi's Fusion Weblog</title><link>http://blogs.msdn.com/b/alanshi/</link><description /><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>GAC Phobia</title><link>http://blogs.msdn.com/b/alanshi/archive/2004/03/28/100765.aspx</link><pubDate>Sun, 28 Mar 2004 20:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:100765</guid><dc:creator>alanshi</dc:creator><slash:comments>34</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alanshi/rsscomments.aspx?WeblogPostID=100765</wfw:commentRss><comments>http://blogs.msdn.com/b/alanshi/archive/2004/03/28/100765.aspx#comments</comments><description>&lt;P&gt;I was recently forwarded a link to a posting entitled &amp;#8220;&lt;A href="http://www.sellsbrothers.com/spout/#Avoid_the_GAC"&gt;Avoid the GAC&lt;/A&gt;&amp;#8221;. I would like to offer some insights into points addressed by this article, to help clarify misconceptions you may have about the GAC, and its intended usage.&lt;/P&gt;
&lt;P&gt;The article argues that the GAC is the managed equivalent of the Windows system32 directory, and suffers from the same DLL sharing problems of the past (e.g. &amp;#8220;DLL hell&amp;#8221;). While it is pointed out that the GAC does facilitate side-by-side storage of DLLs based on the assembly&amp;#8217;s strong identity (something that did not exist with system32), the author reasons that side-by-side storage isn&amp;#8217;t useful because if a new version is available that your app didn&amp;#8217;t use, then the update was pointless. Publisher policy is mentioned as a way to force all apps to use the update, and the argument concludes by saying that this ends up in exactly the same place we started with&amp;#8212;system32.&lt;/P&gt;
&lt;P&gt;A large source of confusion in this topic stems from what publisher policy really is and what it is intended for. There are two very different scenarios for updating an existing assembly:&lt;/P&gt;
&lt;P&gt;1) Critical service updates (e.g. security fixes). These are tactical fixes intended to address specific problems with some previously released version of the component. No new features are in the update, and it is expected that the code is highly compatible with the existing version.&lt;/P&gt;
&lt;P&gt;2) New feature releases. It may be the case that the new code is mostly compatible with the old version of the assembly, but there are no guarantees.&lt;/P&gt;
&lt;P&gt;In case (1), it is clearly desirable to affect all applications on the machine. Because of the critical nature of security fixes, users (and administrators) want to be assured that if they apply a given security fix, that all applications are patched. This is a far better story than trying to hunt down n different applications on the machine that may be using the buggy component, and patching them individually. In the post-slammer-virus world, it should be evident that central servicing for security updates is a critical piece of ensuring machines are protected against malicious code. &lt;/P&gt;
&lt;P&gt;In case (2), we recommend that component authors do not ship publisher policy statements which affect all applications. Because the compatibility of the assembly cannot be guaranteed against older versions, consuming the update should be done on an opt-in basis, rather than by default. You can selectively choose to use a new update for a particular application by utilizing application configuration policy.&lt;/P&gt;
&lt;P&gt;To be clear, I am not advocating putting everything in the GAC. In fact, there was a fair amount of work put into supporting the xcopy deployment model, because of its simplicity and ease of use. An xcopied application is generally easier to move from machine to machine; there&amp;#8217;s no complex setup necessary to install such an application. &lt;/P&gt;
&lt;P&gt;If a publisher policy assembly containing a critical security fix is installed onto a given machine, it will affect all applications that use the older version of the assembly regardless of whether or not that assembly was xcopy deployed or installed into the GAC. But where does the assembly with the actual fixed bits go? The policy will affect every application that used the old version, and clearly there needs to be a place where those applications can find the fixed bits. The GAC is the natural choice here.&lt;/P&gt;
&lt;P&gt;These two scenarios are somewhat confused in the &amp;#8220;avoid the GAC&amp;#8221; article. The author claims that there is no point in providing a new version if it is not intended to affect all applications&amp;#8212;it may as well not be side-by-side. This is not true. As mentioned above, for security fixes, it is definitely desirable to affect all applications. Even so, this does not imply that security fixes should not be side-by-side. Inevitably, there will be cases where a critical security fix will break some application, and users/administrators will need to revert to the old functionality. Side-by-side helps you here, because it allows you to selectively roll back a given application to use the older version, while still allowing all other applications to use the fixed bits. This is a conscious decision by the user/administrator to bypass the security fix because this is an exceptional circumstance. &lt;/P&gt;
&lt;P&gt;For non-security fixes, policy should not be applied to maintain maximum application compatibility. This, however, does not mean that one should avoid the GAC; these points are orthogonal. The GAC is designed to store multiple versions of the same component simultaneously. Two different functional/feature versions can happily live side-by-side without interfering with each other. Critical service updates can also live side-by-side with the pre-serviced version, in order to allow selective rollback where necessary.&lt;/P&gt;
&lt;P&gt;A final point I would like to mention is that although disk space certainly is cheap in today&amp;#8217;s world, sharing assemblies in a single location is still a very commonly requested feature. Sharing the same physical disk space location allows other optimizations, such as reduced memory pressure from not having to load the same copy of the DLL from many different locations (I will resist the urge to dive into related topics like domain neutrality and native images).&lt;/P&gt;
&lt;P&gt;In summary, the old problems of &amp;#8220;DLL hell&amp;#8221; via DLL-name thrashing in system32 do not exist for the GAC. In the world of side-by-side, there are new considerations of how and when to update a component. While xcopy is definitely an attractive way to deploy your application/assembly, it is not the only way to do so, and there are legitimate reasons to make your component globally visible on the machine. Side-by-side allows users to selectively roll back applications which policy may have redirected forward.&lt;BR&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=100765" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/Fusion/">Fusion</category><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/GAC/">GAC</category><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/Policy/">Policy</category></item><item><title>Unification Policy</title><link>http://blogs.msdn.com/b/alanshi/archive/2004/02/15/73244.aspx</link><pubDate>Sun, 15 Feb 2004 08:35:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:73244</guid><dc:creator>alanshi</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alanshi/rsscomments.aspx?WeblogPostID=73244</wfw:commentRss><comments>http://blogs.msdn.com/b/alanshi/archive/2004/02/15/73244.aspx#comments</comments><description>&lt;P&gt;The CLR&amp;#8217;s strict versioning binding policy for strongly-named assemblies was the first step towards alleviating the &amp;#8220;DLL-hell&amp;#8221; problems of the past. Whenever you link to a strongly-named assembly, the exact identity of the referenced assembly is recorded in your assembly&amp;#8217;s metadata, and Fusion will bind to exactly the same version at runtime (binding policy aside). This ensures that the components the developer tested at design-time is exactly what the user will use a run-time.&lt;/P&gt;
&lt;P&gt;Strict binding policy, however, is only a very rudimentary way of enforcing that the assemblies used at run-time match a given developer&amp;#8217;s intentions. Often times, an application or component developer will create a set of assemblies designed to work in conjunction with one another. These assemblies are shipped together as a suite, and the version together as a whole. In a future release of this set of assemblies, new versions of all the components are developed, and are intended to work with the matching versions of other assemblies in that set. The .NET frameworks itself is an excellent example of a stack of related assemblies. There is a v1.0 stack of FX assemblies, and a v1.1 stack of FX assemblies, and the assemblies which comprise the FX stack are designed to only work with other assemblies in that same version of the stack. &lt;/P&gt;
&lt;P&gt;Even though the assemblies in the group certainly will link against the exact version of the other assemblies in that set, this relationship by itself is not enough to guarantee that these assemblies will run together as a coherent stack. This guarantee is often desired by the assembly developer because these assemblies are tested together, and not designed to run against other versions. Binding policy at the app or administrator level can be used to violate the guarantees intended by the app developer.&lt;/P&gt;
&lt;P&gt;A related problem is that even though strongly-named assemblies (either alone, or within a group) can be stored and loaded side-by-side, it may not always be desirable to actually have two (or more) copies of a strongly-named assembly loaded concurrently in a given scope (appdomain / process / etc). Whether a component is truly side-by-side capable at runtime depends on how the component is written. How can a component developer ship different versions of an assembly that is not run-time side-by-side capable, and guarantee that only one version of that component will be loaded at run-time? &lt;/P&gt;
&lt;P&gt;The .NET framework assemblies have both of these problems. During development of the v1.0 product, the CLR / FX test teams explicitly tested the v1.0 FX stack against the v1.0 CLR. The same testing occurred for the v1.1 CLR and the v1.1 FX stack. Side-by-side testing naturally results in an explosive matrix of test cases, and because of this, there was no explicit testing done for mixing and matching v1.0 and v1.1 frameworks assemblies. Furthermore, there are some FX assemblies (I believe winforms is one such example) that are not designed to be run-time side-by-side capable. &lt;/P&gt;
&lt;P&gt;A generalized solution for addressing the problems above is still not yet available. In the interim, a CLR v1.1 feature known as &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconnetframeworkassemblyunificationoverview.asp"&gt;unification policy&lt;/A&gt; was developed that addresses these problems (albeit in a very limited way). Unification is a form of binding policy which occurs after application policy is evaluated, but before publisher policy is applied. A hard-coded table of assemblies which shipped in the v1.1 CLR product is consulted and references to any version of assemblies in that list are automatically redirected to the version of the assembly that shipped in the v1.1 product.&lt;/P&gt;
&lt;P&gt;Through unification policy, it is possible for a v1.0 application to be configured to run against the v1.1 CLR (via the &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/gngrfRequiredRuntime.asp"&gt;&amp;lt;requiredRuntime&amp;gt;&lt;/A&gt; or &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/gnconSupportedRuntimeElement.asp"&gt;&amp;lt;supportedRuntime&amp;gt;&lt;/A&gt; configuration tags), and automatically have the references to the v1.0 FX stack redirected to the appropriate versions for the v1.1 CLR, with no re-compilation, or manual authoring of binding redirects by the developer or end-user. Similarly, an app built against the v1.1 CLR can utilize shared components written for the v1.0 CLR, and again the v1.0 FX references will automatically be redirect to the v1.1 stack. Through unification policy, the v1.1 process will always use v1.1 FX assemblies, and there will not be any mix/match conditions which could cause problems at run-time.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;Unification policy is applied before publisher policy is applied in order to allow for servicing for specific assemblies in the frameworks stack. In the event a security fix for a particular assembly is deployed along with publisher policy for that assembly, we did not want unification policy to interfere with the intended servicing.&lt;/P&gt;
&lt;P&gt;Another scenario which was considered in the design for unification policy is that of &amp;#8220;speedboat&amp;#8221; assemblies. Speedboat assemblies are updates to assemblies which shipped in a given FX stack, with new features, that ship before a new FX stack is shipped with a whole new version of the CLR. Speedboats are designed to be used optionally by app developers on an as needed basis. Since speedboat assemblies are designed to be used per-application, it is not appropriate to ship a publisher policy assembly for speedboats, because publisher policy impacts the entire machine. In order to allow speedboat assemblies to be consumed, a by-pass mechanism was engineered into unification policy. If a &amp;lt;bindingRedirect&amp;gt; statement for an assembly in the FX assembly list is found in the app.exe.config file, unification policy for that assembly will be skipped.&lt;/P&gt;
&lt;P&gt;Because binding redirect statements can be used to by-pass unification rules, it is possible for a malicious app author to force loading v1.0 and v1.1 assemblies at the same time through app.exe.config. For this reason, binding redirects are controlled by a security permission, which is not available by default under partial trust. &lt;/P&gt;
&lt;P&gt;It turns out that the decision to disable binding redirects from partial trust actually ended up hurting no-touch deployment scenarios. When servicing a given application, developers are able to simply modify the application configuration file to specify the binding redirect needed to consume a new version of a strongly-named assembly. The binding redirect saves the developer from having to recompile all applications which referenced the old version of the strongly-named assembly. Servicing zero-touch applications using this technique is not possible because the binding redirect permission is not granted in partial trust.&lt;/P&gt;
&lt;P&gt;For more information about unification, and side-by-side execution of the CLR, you can refer to &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconside-by-sideexecutionfundamentals.asp"&gt;this&lt;/A&gt; MSDN article.&lt;BR&gt;&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=73244" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/Fusion/">Fusion</category><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/Policy/">Policy</category></item><item><title>Why can't I uninstall my assembly?</title><link>http://blogs.msdn.com/b/alanshi/archive/2003/12/10/42690.aspx</link><pubDate>Thu, 11 Dec 2003 04:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:42690</guid><dc:creator>alanshi</dc:creator><slash:comments>45</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alanshi/rsscomments.aspx?WeblogPostID=42690</wfw:commentRss><comments>http://blogs.msdn.com/b/alanshi/archive/2003/12/10/42690.aspx#comments</comments><description>&lt;P&gt;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.&lt;/P&gt;
&lt;P&gt;The reference counts Fusion provides are called &amp;#8220;traced&amp;#8221; 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. &lt;/P&gt;
&lt;P&gt;You can read more about traced reference counts in &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cptools/html/cpgrfglobalassemblycacheutilitygacutilexe.asp"&gt;this&lt;/A&gt; gacutil MSDN document. There is also information about traced reference count in our &lt;A href="http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q317540&amp;"&gt;support article&lt;/A&gt; describing the unmanaged Fusion API.&lt;/P&gt;
&lt;P&gt;When you install your assembly using &lt;A href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpcondeployingcommonlanguageruntimeapplicationusingwindowsinstaller.asp"&gt;MSI&lt;/A&gt; (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.&lt;/P&gt;
&lt;P&gt;If you try to uninstall an assembly in the GAC using &amp;#8220;gacutil -u&amp;#8221;, 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.&lt;/P&gt;
&lt;P&gt;Some customers have reported unusual cases where an assembly installed into the GAC via gacutil &lt;EM&gt;without&lt;/EM&gt; a traced reference count, can later not be uninstalled via &amp;#8220;gacutil -u&amp;#8220;. When the uninstall is attempted, the following message appears:&lt;/P&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P style="MARGIN-RIGHT: 0px"&gt;&lt;FONT size=2&gt;&lt;FONT size=1&gt;&lt;FONT face="Courier New" size=2&gt;Unable to uninstall: assembly is required by one or more applications Pending references:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P style="MARGIN-RIGHT: 0px"&gt;&lt;FONT size=2&gt;&lt;FONT size=1&gt;&lt;FONT size=2&gt;&lt;FONT size=1&gt;&lt;FONT face="Courier New" size=2&gt;SCHEME: &amp;lt;WINDOWS_INSTALLER&amp;gt; ID: &amp;lt;MSI&amp;gt; DESCRIPTION:&amp;lt;&lt;FONT face="Courier New" size=2&gt;Windows Installer&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;&lt;WINDOWS Installer&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=1&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;WINDOWS Installer&gt;&lt;/FONT&gt;
&lt;P style="MARGIN-RIGHT: 0px"&gt;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.&lt;/P&gt;
&lt;P style="MARGIN-RIGHT: 0px"&gt;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:&lt;/P&gt;
&lt;DIR&gt;&lt;FONT size=1&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;[HKCU\Software\Microsoft\Installer\Assemblies\Global]    &lt;/FONT&gt;&lt;/P&gt;&lt;/DIR&gt;
&lt;BLOCKQUOTE dir=ltr style="MARGIN-RIGHT: 0px"&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;[HKLM\SOFTWARE\Classes\Installer\Assemblies\Global]&lt;/FONT&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;/FONT&gt;
&lt;P style="MARGIN-RIGHT: 0px"&gt;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. &lt;/P&gt;
&lt;P style="MARGIN-RIGHT: 0px"&gt;(This tip comes courtesy of our resident MSI expert on the Fusion team, Roberto Sciore).&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=42690" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/Fusion/">Fusion</category><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/GAC/">GAC</category></item><item><title>Access to old blog entries</title><link>http://blogs.msdn.com/b/alanshi/archive/2003/12/10/42582.aspx</link><pubDate>Wed, 10 Dec 2003 20:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:42582</guid><dc:creator>alanshi</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/alanshi/rsscomments.aspx?WeblogPostID=42582</wfw:commentRss><comments>http://blogs.msdn.com/b/alanshi/archive/2003/12/10/42582.aspx#comments</comments><description>&lt;P&gt;Welcome to the home of my new blog! &lt;/P&gt;
&lt;P&gt;All of my old blog entries will not be migrated to this site, however, they will remain available for viewing on the old site at: &lt;A href="http://blogs.gotdotnet.com/alanshi"&gt;http://blogs.gotdotnet.com/alanshi&lt;/A&gt;.&lt;/P&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=42582" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/Fusion/">Fusion</category><category domain="http://blogs.msdn.com/b/alanshi/archive/tags/General/">General</category></item></channel></rss>