转载 在.net中使用GAC

转载出处 https://blog.log4d.com/2011/01/gac/

GAC

GAC是什么?是用来干嘛的?GAC的全称叫做全局程序集缓存,通俗的理解就是存放各种.net平台下面需要使用的dll的地方。GAC的具体目录在windows/ assembly。

喜欢使用破解软件的朋友可能会经常使用替换DLL这招,这个DLL虽然和.net下面的DLL有所不同,但大致起的作用还是一样的:使用共同的动态链接库来提高库复用 ,减少文件体积。在.net平台之前,程序们都把可能用到的公共DLL存放到system32文件夹下。由于版本的不一致及其他原因(将控制信息存放到注册表),造成 了很有名的DLL Hell

最近在读俞甲子的《程序员的自我修养》,中间花了很大的篇幅描述程序编译中 的链接这个过程。而比较巧合的是,我的《C#与.NET 3.5高级程序设计》也正好读到程序集这一块。微软使用了GAC来避免DLL重蹈覆辙。现在,我就来部署一个简单的通用类库到GAC中。

获取强名称(签名)

并不是随便一个DLL都可以放到GAC中,如果这样的话,和之前的DLL Hell也没什么区别了。GAC使用一个强名称(签名)的方式来区分不同的DLL。每个签名 都是独一无二的公钥私钥对。现在我们使用SDK的sn工具为我的DUtil库生成一个snk签名。

打开SDK中的Visual Studio 2008 命令提示,键入sn -k DUtil.snk,结果如下:

F:WorkSpace.netDUtilbinDebug>sn -k DUtil.snk

Microsoft (R) .NET Framework 强名称实用工具 版本 3.5.21022.8

Copyright (c) Microsoft Corporation. All rights reserved.

密钥对被写入 DUtil.snk

这样我们就得到了一个snk签名文件。

为程序集设置签名

现在我们得到了一个签名文件,但是还没有把这个签名应用到程序中,在程序的assembly.cs文件中加入[assembly: AssemblyKeyFile("dutil.snk")],这个dutil.snk可以是绝对路径,我使用的是主目录中的snk文件。

编译解决方案,生成的.dll文件就包含了签名。

此时编译器会出现一个警告:

警告 1 使用命令行选项"/keyfile"或适当的项目设置代替"AssemblyKeyFile" F:WorkSpace.netDUtilPropertiesAssemblyInfo.cs 38 12 DUtil

既然VS建议我们用选项设定,那我们就用项目选项页设定key。如下图所示:

PS:我测试过,生成DLL之后,就算删除签名使用的snk文件,依然可以正常使用。即snk文件只有在编译时候使用。

安装到GAC

安装到GAC有两种办法,一种是把DLL拖入windows/assembly目录下(不是复制粘贴,是拖动),另外一种是使用gacutil。

在Win7下,拖动的话会遇到权限问题,如下图所示

在gacutil下面也会遇到如下错误

F:WorkSpace.netDUtilbinDebug>gacutil -i DUtil.dll
Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.21022.8
Copyright (c) Microsoft Corporation.  All rights reserved.

将程序集添加到缓存失败: 拒绝访问。您可能没有执行此任务的管理凭据。请与您的系统管

理员联系以获得帮助。

解决的办法就是进入命令行时候用管理员身份进入,执行之后显示如下

F:WorkSpace.netDUtilbinDebug>gacutil -i DUtil.dll
Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.21022.8
Copyright (c) Microsoft Corporation.  All rights reserved.

程序集已成功添加到缓存中

这时候查看windows/assembly目录,就会发现DUtil已经在里面了。

用TotalCommander打开windows/assembly,会发现里面有GAC/GAC_32/GAC_MSIL这几个文件夹,我的DUtil安装到c: WindowsassemblyGAC_MSILDUtil.1.0.0__35f4c1ba225b3cc6DUtil.dll,这个路径包含了版本,签名,通过 这种方式,就能避免版本和错误dll的问题了。

使用GAC的dll

打开任意一个项目,添加引用时候,选择编译出来的DUtil.dll即可。查看具体属性,就会发现,这个DLL并未复制到本地,因为它可以从GAC中获取了。

这时候如果我们删除引用地方的DLL,会发现程序依然可以正确跑起来,说明我们的DLL确实来自GAC。(Update:当引用DLL文件存在时候,优先引用此DLL ,不存在才引用GAC的DLL)

PS:不要尝试去打开windows/assembly目录来引用,你会发现你徒劳的。

卸载GAC中的DLL

一句话搞定

C:Windowssystem32>gacutil -u DUtil
Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.21022.8
Copyright (c) Microsoft Corporation.  All rights reserved.

程序集: DUtil, Version=0.1.0.0, Culture=neutral, PublicKeyToken=35f4c1ba225b3cc6

, processorArchitecture=MSIL

已卸载: DUtil, Version=0.1.0.0, Culture=neutral, PublicKeyToken=35f4c1ba225b3cc6

, processorArchitecture=MSIL

卸载的程序集数 = 1

失败次数 = 0

这样就把特定目标的DLL卸载了。

参考文章

除了上文提到的两本书,还参考了MSDN中的815808文章,文章名如何在 Visual C# .NET 中将程序集安装到全局程序集缓存中

时间: 2024-08-05 06:40:31

转载 在.net中使用GAC的相关文章

转载:C#中事件的由来

原文地址 http://www.tracefact.net/CSharp-Programming/Delegates-and-Events-in-CSharp.aspx 感谢博主分享! 我们继续思考转载:C# 中的委托中的例子程序:上面的三个方法都定义在Programe类中,这样做是为了理解的方便,实际应用中,通常都是 GreetPeople 在一个类中,ChineseGreeting和 EnglishGreeting 在另外的类中.现在你已经对委托有了初步了解,是时候对上面的例子做个改进了.假

【转载】lucene中Field.Index,Field.Store详解

lucene在doc.add(new Field("content",curArt.getContent(),Field.Store.NO,Field.Index.TOKENIZED)); Field有两个属性可选:存储和索引. 通过存储属性你可以控制是否对这个Field进行存储: 通过索引属性你可以控制是否对该Field进行索引. 事实上对这两个属性的正确组合很重要. Field.Index Field.Store 说明 TOKENIZED(分词) YES 被分词索引且存储 TOKE

转载《设计中的设计》读后感

<设计中的设计>读后感 当我拿到这本书时第一想法就是把他认真仔细的看一遍,去和大师握手,一起去感悟设计的博大,一起倾听世界.    这本书是日本设计大师'原研哉'的著作,他为我们写了本相当于是大众的读物,让每个人都能看,都能了解设计这个门路怎么去走,怎么去走好着条设计之路?大师还邀请了一些对设计感兴趣的设计师一起观望设计世界.    在这本书里我明白了一个道理,"只要脚踏实地,就能走好设计这条路".原研哉曾说过这样一句话'当你因为读完这本观念设计书而感到越来越不懂设计时,这

【转载】Spring中的applicationContext.xml与SpringMVC的xxx-servlet.xml的区别

一直搞不明白两者的区别. 如果使用了SpringMVC,事实上,bean的配置完全可以在xxx-servlet.xml中进行配置.为什么需要applicationContext.xml?一定必须? 一. 因为直接使用了SpringMVC,所以之前一直不明白xxx-servlet.xml和applicationContext.xml是如何区别的,其实如果直接使用SpringMVC是可以不添加applicationContext.xml文件的. 使用applicationContext.xml文件时

【转载】Spring中DispatcherServlet与ContextLoaderListener的区别

昨天在写springmvc的时候,在web.xml中配置了DispatcherServlet,如下: <servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>

转载:NetBeans中如何运行GUI

这篇入门教程将教会您怎样创建一个简单的人机交互界面以及向其中添加简单 的后台功能. 特别地,我们将向您展示如何按 Swing 规范编写控制按钮和域代 码. 我们将会使用到布局管理.设计简单 GUI 界面以及添加一些“按钮(button) ”和“文本字段(text field)”组件. “文本字段”是用来接收输入和显示输出 的,“按钮”在前端用来起动相应功能. 我们将创建的应用程序会是一个简单但 实用的计算器. 获得更多GUI设计功能.视频及文档,请参见Desgning a Swing GUI i

【转载】C++中结构体的声明和定义

http://blog.csdn.net/whuslei/article/details/5665289 1  //定义一个结构体,类型为struct Student 2  struct  Student      3  { 4      string name; 5      double eng; 6      double ch; 7  };  8    9  //定义了一个结构体,类型为struct Student:且定义了一个结构体实例,名叫Stu 10  struct  Studen

好文转载--无线物联网中CoAP协议的研究与实现

无线物联网中CoAP协议的研究与实现 时间:2013-04-09?来源:电子科技 作者:汤春明,张 荧,吴宇平 关键字:CoAP???无线???物联网???协议?????? 摘要:由于物联网中的很多设备都是资源受限型的,即只有少量的内存空间和有限的计算能力,所以传统的HTTP协议应用在物联网上就显得过于庞大而不适用.IETF的CoRE工作组提出了一种基于REST架构的CoAP协议.CoAP是6LowPAN协议栈中的应用层协议.该文在详细介绍了CoAP协议的内容.特点和交互模型后,在uIPv6 S

(转载)JDK中的设计模式

写的很好,学习道路更轻松一些 原文地址:http://blog.csdn.net/gtuu0123/article/details/6114197 JDK中设计模式 分类: Java相关 设计模式 2011-01-03 20:42 3550人阅读 评论(6) 收藏 举报 jdk设计模式swingclassloaderdocumentationiterator 本文主要是归纳了JDK中所包含的设计模式,包括作用和其设计类图. 首先来个总结,具体的某个模式可以一个一个慢慢写,希望能对研究JDK和设计