CLR查詢和引導程式集的方式

2021-07-28 11:29:48 字數 3800 閱讀 3930

c#開發者在開發winform程式、asp.net web(mvc)程式等,不可避免的在專案中引用許多第三方的dll程式集,

編譯後引用的dll都放在根目錄下。以我個人作品 

autoproject studio 自動化專案生成器為例,由於需要支援sql server、

oracle、mysql、postgresql、db2、sybase、infomix、sqlite、access等多種資料庫,

所以引用了dmprovider.dll、

ibm.data.db2.dll、ibm.data.informix.dll、mysql.data.dll、npgsql.dll、sqlite.interop.dll、

system.data.dll、

system.data.oracleclient.dll、sybase.adonet4.aseclient.dll 等dll,參考下圖:

隨著專案的日益增大,根目錄下充滿了各種各樣的dll,非常的不美觀。

如果能夠把dll按照想要的目錄來存放,那麼系統就美觀多了。

此問題就涉及到clr查詢和引導程式集的方式

系統搜尋dll的目錄以及順序

clr解析乙個程式集會在乙個根目錄內進行搜尋,整個探索過程又稱probing,這個根目錄很顯然就是當前包含當前程式集的目錄。

程式搜尋dll的順序如下(區分強名稱簽名、沒有強名稱簽名的程式集)

沒有做強名稱簽名的程式集

程式的根目錄

根目錄下面,與被引用程式集同名的子目錄

根目錄下面被明確定義為私有目錄的子目錄

在目錄中查詢的時候,如果dll查詢不到,則會嘗試查詢同名的exe

如果程式集帶有區域性,而不是語言中立的,則還會嘗試查詢以語言區域命名的子目錄

強名稱簽名的程式集

全域性程式集快取

如果有定義codebase,則以codebase定義為準,如果 codebase指定的路徑找不到,則直接報告錯誤

程式的根目錄

根目錄下面,與被引用程式集同名的子目錄

根目錄下面被明確定義為私有目錄的子目錄

在目錄中查詢的時候,如果dll查詢不到,則會嘗試查詢同名的exe

如果程式集帶有區域性,而不是語言中立的,則還會嘗試查詢以語言區域命名的子目錄

如何讓程式識別不同目錄下的dll?

我們看到,上面的順序無論是否有強名稱簽名看,都提到了乙個名詞 「私有目錄」。

針對該問題,微軟提供了元素, 在配置檔案中自定義儲存目錄。

1

<?xml version="

1.0" encoding="

utf-8

" ?>23

45"false

" />6"

urn:schemas-microsoft-com:asm.v1

">

7"bin;bin2\subbin;bin3

" />89

10

上述 privatepath中的"bin;bin2\subbin;bin3",其中bin是預設編譯輸出目錄,bin2、bin3 是自定義目錄,subbin是bin2下的子目錄。

把dll分別放入上述目錄中,程式執行正常。

這是最簡單的方法,當然也有一定的侷限性,就是沒法對dll做控制。另外,無法解決第三方dllimport中引入的程式集不在根目錄下的問題。

但是該方法基本解決了分目錄儲存的問題。

方法二:訂閱程式集解析事件 assemblyresolve 在**中解析

通過這個事件,我們可以在程式集解析時,根據不同的程式集做不用的處理,比如載入x86的程式集還是64位的程式集,當然也就可以指定程式集目錄了

這也正是 assembly.load 和 assembly.loadfrom 等方法的用武之地。

1

using

system;

2using

system.io;

3using

system.reflection;

4using

system.windows.forms;56

namespace723

24///

25///

解析當前應用程式域內指定目錄下的dll

26///

27///

28///

29///

30private

static assembly currentdomain_assemblyresolve(object

sender,resolveeventargs args)

31.dll

",path);

35return

assembly.loadfrom(path);36}

37}38 }

方法三:

1

using

system;

2using

system.io;

3using

system.reflection;

4using

system.windows.forms;56

namespace723

2425

///26

///設定程式集所在的指定目錄並解析dll

27///

28private

static

void

setprivatebinpath()

29.config"39

",null

,setup);

41int ret =newdomain.executeassemblybyname(currentassembly.fullname);

4243

44 environment.exitcode =ret;

45 environment.exit(0

);46

return;47

}48}49

}50 }

方法四:在載入使用到的dll**之前重置當前環境的目錄通過 environment.currentdirectory=custompath ,切換目錄後,在呼叫dll方法時執行正常。

處理 [dllimport] 中的程式集的載入,此處提供用一種方式來處理:增加環境變數。

c#**如下:

static

void addenvironmentpaths(ienumerablepaths)

;

string newpath = string

.join(path.pathseparator.tostring(), path.concat(paths));

environment.setenvironmentvariable(

"path

", newpath);

}

CLR 程式集和命名空間

控制台應用program並非只是含有元資料的pe檔案,他還是程式集 assembly 程式集是乙個或多個型別定義檔案及資源檔案的集合。在程式及的所有檔案中,有乙個檔案容納了清單 manifest 清單也是乙個元資料表集合,表中主要包含作為程式集組成部分的那些檔案的名稱。此外,還描述了程式集的版本 語...

CLR 共享程式集和強命名程式集

2017年08月12日 23 36 52 生活常識 閱讀數 187 clr支援兩種型別的程式集 弱命名程式集 weakly named assembly 和強命名程式集 strongly named assembly 二者的區別 強命名程式集使用發布者的公鑰 私鑰進行了簽名。這一堆金鑰允許對程式集進...

C 如何引導程式執行目錄外的程式集

我們的應用程式部署的時候,目錄結構一般不會只有執行程式的目錄這乙個,我們可能在執行目錄下建子目錄,也可能使用system32目錄,也可能使用其它第三方的程式集。net程式集 首先會在gac中搜尋相應的版本,如果未找到則會應用程式配置檔案中找 如果配置 最後到應用程式所在的路徑搜尋。configura...