【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 中將程序集安裝到全局程序集緩存中


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM