生成程序集后自动将其加入GAC并包含调试信息。






4.43/5 (11投票s)
2007年8月10日
4分钟阅读

65850
本文介绍了如何修改VS项目,使其在生成后自动将程序集加入GAC,并可选择性地包含调试信息。
引言
本文介绍如何配置VS 2003或2005项目,在生成后自动将程序集加入GAC。文章还介绍了如何将调试信息一同移入GAC。
背景
几年前,我在处理包含大量共享代码的项目时首次使用了这种技术。大多数框架程序集被放入GAC供项目共享。这成了一种有用的技术,可以在与生产环境部署相同的方式下调试项目。
在项目文件中,您可以通过在“生成后事件”中添加以下内容来在生成后自动将程序集加入GAC。"C:\Program files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe"
-i "$(TargetPath)"
显然,如果您处于团队环境中,您可能希望使用环境变量,例如%ProgramFiles%
。据我所知,没有指向完整路径的环境变量。如果您打开VS命令提示符,该目录会被添加到path变量中,但奇怪的是,在生成过程中无法使用。
注意:对于2003,路径是C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin。添加此项后,您需要解决问题的另一面:在生成前取消GAC注册。在“生成前事件”中添加
"C:\Program files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe"
-u $(TargetName)
很多人可能已经自己摸索出来,或者已经知道了。我遇到的问题是,一旦我将一个程序集加入了GAC,无论我如何生成程序集,调试信息都不会随之而去。这时事情变得有点奇怪。GAC实际上是windows\assembly文件夹下的一个高度保密的文件夹系列。如果您在资源管理器中打开此文件夹,您会看到一个“特殊”窗口,允许您执行GAC管理(例如,拖放安装、删除等)。如果您打开命令提示符并转到同一个目录,您会看到类似这样的内容
Volume in drive C has no label.
Volume Serial Number is D43F-9977
Directory of C:\WINDOWS\assembly
10/06/2006 01:22 PM <DIR> GAC
10/16/2006 04:25 PM <DIR> GAC_32
11/20/2006 01:42 PM <DIR> GAC_MSIL
07/11/2006 09:44 AM <DIR> NativeImages1_v1.1.4322
10/19/2006 05:07 PM <DIR> NativeImages_v2.0.50727_32
11/20/2006 01:42 PM <DIR> temp
11/20/2006 01:42 PM <DIR> tmp
0 File(s) 0 bytes
7 Dir(s) 11,621,462,016 bytes free
这就是真正存放内容的超级机密GAC区域。GAC文件夹用于.NET 1.1程序集,GAC_MSIL(主要是)用于.NET 2.0程序集。如果您进入GAC_MSIL文件夹(对于那些记不起DOS命令的年轻一代,输入“cd GAC_MSIL
”),您会看到一系列与您的GAC中的程序集同名的目录(至少是2.0程序集)。例如,我们来处理System.Xml。进入System.Xml目录(“cd System.Xml
”),您会看到
Volume in drive C has no label.
Volume Serial Number is D43F-9977
Directory of C:\WINDOWS\assembly\GAC_MSIL\System.Xml
10/16/2006 04:24 PM <DIR> .
10/16/2006 04:24 PM <DIR> ..
10/16/2006 04:24 PM <DIR> 2.0.0.0__b77a5c561934e089
0 File(s) 0 bytes
3 Dir(s) 11,621,388,288 bytes free
这就是为什么同一个程序集的多个版本可以同时存在于GAC中的原因。文件夹名称的构造方式如下:%VersionInfo%_%CultureInfo%_%PublicKeyToken%。因此,如果您已经将一个程序集的1.0和1.1版本加入了GAC,这里将有两个文件夹。我猜测该令牌的存在是为了防止两个不同的供应商发布同名程序集,但这只是我的猜测。继续。进入此文件夹,您会找到您丢失的程序集。
Volume in drive C has no label.
Volume Serial Number is D43F-9977
Directory of C:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089
10/16/2006 04:24 PM <DIR> .
10/16/2006 04:24 PM <DIR> ..
10/16/2006 04:24 PM 2,035,712 System.XML.dll
1 File(s) 2,035,712 bytes
2 Dir(s) 11,621,388,288 bytes free
如果您想为已加入GAC的程序集提供调试信息,PDB文件需要放在这里。并且没有自动方法将其放到这里。我通常会尽量让生成前后的事件保持通用,但在这种情况下,我不知道如何做到这一点,除非使用某种辅助程序。如果您在生成后事件中添加以下命令,可以复制PDB到这里
copy "$(TargetDir)$(TargetName).pdb" "C:\windows\assembly\GAC_MSIL
\$AssemblyName$\$VersionNumber$__$PublicKeyToken$\"
将$AssemblyName$
替换为您的程序集名称等。($()
宏是msbuild实际识别的宏,请勿更改它们)。$AssemblyName$
、$VersionNumber$和$PublicKeyToken$变量不是宏。您需要显式定义它们或创建一个辅助程序来发现它们。我过去曾编写过一个小命令行实用程序来解析程序集信息并将其调试信息放入GAC。这有点超出本文的范围,但我稍后可能会介绍。以下是注意事项。微软显然不希望您直接修改这些目录,所以他们进行了保护。您“无法”以任何方式访问它们,只能通过命令行。这意味着您不能使用一个小脚本文件来完成,也不能用C#完成,您“只能”通过命令行或.bat文件来完成。(相信我,我尝试过)。所以,如果您尝试自动化此过程,最好的方法是写一个批处理文件然后运行它。有点笨拙,但有效。我发现当您需要生成并加入GAC多个版本的程序集时,这种方法效果不太好。在这种情况下,我取消了生成前事件(注销),并将生成后事件更改为
"C:\Program files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe"
-i "$(TargetPath)" /f
这意味着如果GAC中已存在现有版本,则强制替换。这使得我可以生成2.1而无需删除2.0(以防万一有什么依赖于2.0)。