【C# 程序集】在.net中使用GAC 全局程序集缓存
原文地址:https://blog.alswl.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。如下图所示:

选择sha256 加密等级更高
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 中将程序集安装到全局程序集缓存中。
【C# 程序集】在.net中使用GAC 全局程序集缓存的更多相关文章
- 【C# 程序集】把自己的程序集添加|卸载 到GAC 全局程序集缓存中
添加全局程序集缓存 Global Assembly Cache Tool (Gacutil.exe) 操作环境windows10+vs2019 cmd.exe位置在 C:\Windows\System ...
- 如何将程序集安装到全局程序集缓存GAC
针对一些类库项目或用户控件项目(一般来说,这类项目最后编译生成的是一个或多个dll文件),在程序开发完成后,有时需要将开发的程序集(dll文件)安装部署到GAC(全局程序集缓存)中,以便其他的程序也可 ...
- .NET 中的 GAC
GAC : ———> 全局程序集缓存 介绍GAC的好文章(怎么:生成SNK,给项目加强名称,加入到GAC,多个版本共存,介绍了不同的工具): http://www.makaidong.com/% ...
- 【转】Gacutil.exe(全局程序集缓存工具)
全局程序集缓存工具使您可以查看和操作全局程序集缓存和下载缓存的内容. 安装 Visual Studio 和 Windows SDK 时会自动安装此工具. 要运行工具,我们建议您使用 Visual St ...
- Gacutil.exe(全局程序集缓存工具)
全局程序集缓存 .NET Framework (current version) 其他版本 安装有公共语言运行时的每台计算机都具有称为全局程序集缓存的计算机范围内的代码缓存.全局程序集缓存中存储了专门 ...
- 全局程序集缓存工具(Gacutil.exe)用法详解
全局程序集缓存工具 (Gacutil.exe) 全局程序集缓存工具使您可以查看和操作全局程序集缓存和下载缓存的内容. 复制 gacutil [options] [assemblyName | asse ...
- 29防止程序集被篡改仿冒,全局程序集缓存GAC
为什么需要强名称程序集和数字签名 有一个类库项目ClassLib,对应的程序集是ClassLib.dll.当前控制台项目引用ClassLib.dll程序集的方式有2种: 1.通过添加现有项目 文件 ...
- 在.net中使用GAC
转自:http://blog.log4d.com/2011/01/gac/ GAC GAC是什么?是用来干嘛的?GAC的全称叫做全局程序集缓存,通俗的理解就是存放各种.net平台下面需要使用的dll的 ...
- 转载 在.net中使用GAC
转载出处 https://blog.log4d.com/2011/01/gac/ GAC GAC是什么?是用来干嘛的?GAC的全称叫做全局程序集缓存,通俗的理解就是存放各种.net平台下面需要使用的d ...
随机推荐
- 通过CVE-2021-43297漏洞在Apache Dubbo<=2.7.13下实现RCE
目录 0 前言 1 找源头 1.1 找到触发点 1.2 可用的gadget 1.3 向上推触发点 2 构造poc 2.1 开启HttpServer 2.2 hessian2序列化过程简述 3 poc ...
- MySQL查询处理——逻辑查询处理和物理查询处理
对于查询处理,可将其分为逻辑查询处理和物理查询处理.逻辑查询处理表示执行查询应该产生什么样的结果,而物理查询代表MySQL数据库是如何得到结果的. 逻辑查询处理 MySQL真正的执行顺序如下: (8) ...
- 删除修改docker网络环境
安装工具包 yum install bridge-utils -y 设置docker0 ip网段 ip link set docker0 down brctl delbr docker0 brctl ...
- Arduino+ESP32 之 SD卡读写
背景知识: ESP32有两种使用SD卡的方法,一种是使用SPI接口访问SD卡,另一种是使用SDMMC接口访问SD卡 . Arduino core for the ESP32中SPI方式占用4个IO口, ...
- JavaScript之Promise实现原理(手写简易版本 MPromise)
手写 Promise 实现 Promise的基本使用 Promise定义及用法详情文档:Promise MAD文档 function testPromise(param) { return new P ...
- java 多线程 start方法 run方法 简单介绍。
一 start开启一个多线程, run 只是一个内部的方法. package com.aaa.threaddemo; /* * start方法的作用? * 在 Java中启动多线程调用的是start方 ...
- mybatis 接口中定义方法、映射文件、实体类之间的关系?
一.定义实体类 ,注意需求 是一对多还是多对一. 这里用员工和部门 多对一的关系举例. package com.zs.entity; /* * /* * 多对一? * 多个员工 对应一个部门 一个 ...
- Visual Studio 2010 怎么查看函数的重载数量、范围、种类等
将光标放置在()括号内,然后按ctrl + shift + 空格 ,这样就会显示出具体的重载数量与种类,按上键或下键就可以翻看了:
- War包是什么??
感谢大佬: https://blog.csdn.net/Stitch__/article/details/88091745 https://www.jianshu.com/p/3b5c45e8e5bd ...
- php截取字符串,避免乱码
转载请注明来源:https://www.cnblogs.com/hookjc/ 1. 截取GB2312中文字符串 <?php//截取中文字符串 function mysubstr($str, $ ...