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卸载了。
GAC的更多相关文章
- Uninstall from GAC In C# code
How do I uninstall the GAC from my C# application. I am not able to uninstall, the particular exe an ...
- 在.net中使用GAC
转自:http://blog.log4d.com/2011/01/gac/ GAC GAC是什么?是用来干嘛的?GAC的全称叫做全局程序集缓存,通俗的理解就是存放各种.net平台下面需要使用的dll的 ...
- 将.NET dll注册到GAC(Global Assembly Cache)中
当发现有多个解决方案引用一个dll时,为了不重复引用所以将.net的一个dll注册到GAC中去. gacutil.exe. 记得使用管理员权限打开 开始菜单-Microsoft Visual Stud ...
- asp.net mvc本地程序集和GAC的程序集冲突解决方法
一个从asp.net mvc 3升级到asp.net mvc 4的项目发生了如下错误: [A]System.Web.WebPages.Razor.Configuration.HostSection c ...
- .net framework 4.0 从 GAC 卸载 程序集
.net framework 4.0 的 GAC 目录: C:\Windows\Microsoft.NET\assembly\GAC_MSIL 要卸载,仍然使用 gacutil 命令,不要带扩展名: ...
- 导出你的GAC Assembly中的DLLS -- 金大昊(jindahao)
导出你的GAC Assembly中的DLLS 方法1: CMD命令中,进入C:\windows\assembly,然后XCOPY GAC_MSIL c:\temp /E 这样就得到了dlls了,以 ...
- GAC(Global Assembly Cache)注册/卸载 dll
当发现有多个解决方案引用一个dll时,为了不重复引用所以将.net的一个dll注册到GAC中去. gacutil.exe. 记得使用管理员权限打开 开始菜单-Microsoft Visual Stud ...
- 转载 在.net中使用GAC
转载出处 https://blog.log4d.com/2011/01/gac/ GAC GAC是什么?是用来干嘛的?GAC的全称叫做全局程序集缓存,通俗的理解就是存放各种.net平台下面需要使用的d ...
- GAC write failed when upgrade with InstallShield
在接近final-build的时候,突然发现当前版本从上一个版本upgrade的时候,需要写到GAC (Global Assembly Cache)的assambly会写失败掉.但是只会在特定的Mic ...
- GAC的理解及其作用
转:http://www.cnblogs.com/smallstone/archive/2010/06/29/1767508.html 一.GAC的作用 全称是Global Assembly Cach ...
随机推荐
- python 12篇 mock接口之flask模块
一.使用pip install flask按照flask模块. import flask,json # 轻量级web开发框架 server = flask.Flask(__name__) @serve ...
- golang开发:Error的使用
Error是Go语言开发中最基础也是最重要的部分,跟其他语言的try catch的作用基本一致,想想在PHP JAVA开发中,try catch 不会使用,或者使用不灵活,就无法感知到程序运行中出现了 ...
- C语言:float表示范围
#include <stdio.h> #include <limits.h> //整数限制 #include <float.h> //浮点数限制 void main ...
- 检测当前手机正在运行的APP
import re #一定要引入,否则不提示错误,但找不到目标def jiance(sjh): aakk="adb -s {0} shell dumpsys activity activit ...
- Java基础00-反射35
1. 类加载器 深入理解java类加载器类加载器 1.1 类加载 类加载或类初始化的三个步骤:类的加载.类的连接.类的初始化 加载:类加载过程的一个阶段:通过一个类的完全限定查找此类字节码文件,并利用 ...
- python之数据驱动ddt操作(方法三)
import unittestfrom selenium import webdriverfrom selenium.webdriver.common.by import Byimport unitt ...
- 【搜索】单词方阵 luogu-1101
题目描述 给一n×n的字母方阵,内可能蕴含多个"yizhong"单词.单词在方阵中是沿着同一方向连续摆放的.摆放可沿着8个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间 ...
- 虚拟机安装RHEL8.0.0
在VMware Workstations 15.0.0中安装RHEL8.0.0 使用到的软件和主机基本配置 此处宿主机基本硬件配置:i3-7100U 4核,内存:12G 虚拟化软件:VMware Wo ...
- xshell中操作服务器笔记
sudo su 获取root权限 cd 切换到相应文件夹 ll ls 查看文件夹内容 cp file folder 复制文件到文件夹 \cp为强制覆盖不提示 cp -r /packageA/* /cp ...
- 简单的Postman,还能玩出花?
Postman是一款我们在工作中使用频率非常高的API调试工具,估计很多童鞋在使用它时也比较粗暴,填好接口地址.参数,直接send就完事了,估计大家要说了,这么简单的东西还能玩出什么花来.今天就和大家 ...