转自:http://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 中将程序集安装到全局程序集缓存中

在.net中使用GAC的更多相关文章

  1. 转载 在.net中使用GAC

    转载出处 https://blog.log4d.com/2011/01/gac/ GAC GAC是什么?是用来干嘛的?GAC的全称叫做全局程序集缓存,通俗的理解就是存放各种.net平台下面需要使用的d ...

  2. .NET 中的 GAC

    GAC : ———> 全局程序集缓存 介绍GAC的好文章(怎么:生成SNK,给项目加强名称,加入到GAC,多个版本共存,介绍了不同的工具): http://www.makaidong.com/% ...

  3. 在Visual Studio开发的项目中引用GAC中的dll

    Open the windows Run dialog (Windows Key + r) Type C:\Windows\assembly\gac_msil. This is some sort o ...

  4. 【C# 程序集】在.net中使用GAC 全局程序集缓存

    原文地址:https://blog.alswl.com/2011/01/gac/ GAC GAC是什么?是用来干嘛的?GAC的全称叫做全局程序集缓存,通俗的理解就是存放各种.net平台下面需要使用的d ...

  5. C# 注册DLL至GAC 并在添加引用中使用该DLL

    本文链接:https://blog.csdn.net/World3000/article/details/819835901,创建一个强签名的类库 类库属性中新建秘钥文件 或者使用工具 使用命令sn ...

  6. 全局程序集缓存GAC

    GAC中的所有的Assembly都会存放在系统目录"%winroot%\assembly下面.放在系统目录下的好处之一是可以让系统管理员通过用户权限来控制Assembly的访问. 目录:C: ...

  7. C#中的程序集和命名空间

    C#中的程序集和命名空间 如果说命名空间是类库的逻辑组织形式,那么程序集就是类库的物理组织形式.只有同时指定类型所在的命名空间及实现该类型的程序集,才能完全限定该类型.<精通.NET核心技术-- ...

  8. 《精通C#》十四章-.NET程序集入门

    在书中,这一章节的开头说的是自定义命名空间和使用命名空间,在以我目前有限的经验来说,程序集就是一个类库经过编译之后,所生成的一个在引用命名空间,进而使用该文件中已经定义好的字段,属性以及方法的文件,以 ...

  9. [转]程序集之GAC---Global Assembly Cache

    本文转自:http://www.cnblogs.com/jhxk/articles/2564295.html 1.什么是GAC?GAC解决什么问题? GAC全称为: Global Assembly C ...

随机推荐

  1. iOS AppIcon尺寸和上传ITunes构建版本尺寸

    避免忘记. 记录一下 App Icon: 29X2940X4058X5876X7687X8780X80120X120152X152167X167180X180 ITunes构建版本: 1242 x 2 ...

  2. day1学习

    python 2 和 3 的区别 1.用户输入的命令:python 2 中是raw_input(""):python 3 中是input(""). 2.默认字符 ...

  3. [Django]下拉表单与模型查询

    前言:本文主要针对自定义下拉表单制作,下拉表单的内容是取至于数据库,即动态实现下拉表单 正文: 动态实现下拉表单有两种方法: 一.自己手动写 html 模板中的 <form ...> &l ...

  4. UDP

    我们通过以下代码来连了解以下UPD 首先我们先创建Server类 package cn.a.qwe; import java.net.DatagramPacket; import java.net.D ...

  5. HDU3466 Proud Merchants[背包DP 条件限制]

    Proud Merchants Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) ...

  6. 微软准备开源PowerShell

    微软有计划在近期内开源PowerShell 近日微软再次在向开源投出橄榄枝, PowerShell是面向Windows和Windows Server的自动化平台和脚本语言,帮助用户简化系统的管理.在纳 ...

  7. 我离baidu.com有几跳

    一.背景 最近,读了网易游戏面试经验(三) - cotyb - 博客园之后,自己尝试着在windows下tracert了一下baidu.com,结果如下图一所示,发现从tracert的结果看,似乎一直 ...

  8. RFID考试背诵

    简答题: 简述RFID标准多元化的原因: 由不同的技术因素.利益因素导致: 工作频率分布在低频至微波的多个频段中,频率不同,技术差异大. 作用距离的差异导致标准不同:因为应答器分为有源.无源两种工作方 ...

  9. 关于ES6新增的东西(二)

    六.原生Promise 就是一个对象,用来传递异步操作的数据(消息) pending(等待.处理中)-> Resolve(完成.fullFilled) -> Rejected(拒绝.失败) ...

  10. on事件委托

    on绑定多个事件,off解绑事件,one事件只执行一次 on除了能够处理未来事件,还可以对事件进行委托处理 $('div').on('click', 'p', function(event)(也就是通 ...