2015-01-07 99 views
1

ASP.Net如何設置本機DLL的搜索路徑嗎?我需要能夠在我自己的代碼中複製邏輯。ASP.Net中的DllImport如何查找DLL?

欲瞭解更多背景信息:我正在維護一個託管庫(稱爲Managed.DLL),它封裝了一個本地庫(稱爲Native.DLL),該庫又使用另一個本機DLL(如Driver.DLL)。到目前爲止,Managed.DLL一直使用.Net的DllImport屬性從Native.DLL導入函數,但現在我必須將其更改爲手動編碼調用LoadLibrary和GetProcAddress以獲得更多控制;特別是,我需要能夠調用FreeLibrary來卸載Native.DLL,並且當通過DllImport加載Native.DLL時,我無法執行此操作。

問題來了:雖然只有DllImport(「Native.DLL」)足以找到Native.DLL和Driver.DLL,但當Managed.DLL爲「是」時,調用LoadLibrary(「Native.DLL」)時會失敗並顯示ERROR_FILE_NOT_FOUND用於ASP.Net應用程序,因爲包含Managed.DLL的目錄不在本機代碼DLL的搜索路徑中。

我的第一個想法是使用Assembly.GetExecutingAssembly()。位置,然後用完整路徑發出LoadLibrary調用,但是Native.DLL無法找到Driver.DLL,因爲包含它們的目錄仍然不在搜索路徑。

我可以解決此通過使用Assembly.GetExecutingAssembly()位置值來設置與SetDllDirectory會原生DLL搜索路徑,但這有兩大缺點:

1)SetDllDirectory會改變全球WinAPI的設置,並能干擾同樣使用本地代碼DLL的同一ASP.Net工作進程中的其他代碼;我也已經證實,使用DllImport屬性不會混淆這個設置,所以現在改變它可能確實會破壞以前工作的東西。

2)它仍然不適用於在Visual Studio中調試ASP.Net應用程序,因爲VS會將託管資源複製到臨時目錄中,但會將本機DLL保留在項目構建目錄中,因此它們會以不同的方式結束調試會話中的位置(並且每個調試會話都會擦除臨時目錄,因此手動將本機DLL複製到它中也不起作用;我必須將本機DLL複製到IIS的調試會話目錄中才能找到它們,這是顯然不可接受的解決方案)

我真的很想在這裏做兼容的事情,但到目前爲止還沒有能夠找出這是什麼,經過幾天的無果搜索任何指針將不勝感激。

回答

0

要回答我的問題:

1)我沒有關於Managed.DLL的複製是「影子拷貝」(James Schubert解釋它比微軟官方文檔,我見過好多了)和關鍵字訣竅是使用Assembly.CodeBase而不是Assembly.Location,因爲前者給出了Managed.DLL的原始位置,後者是影子副本的位置(John Sibly and Sneal共享了很好的代碼片段,以便從Assembly.CodeBase中的URI中提取目錄名稱)。

2)使用本機DLL的依賴關係的方法是在需要之前使用LoadLibrary明確加載它們(並且因爲這會增加它們的引用計數,並且在完成時也將它們釋放到FreeLibrary)。

因此,加載順序是

string dir = Assembly.GetExecutingAssembly().CodeBase; 
dir = new Uri(dir).LocalPath; 
dir = Path.GetDirectoryName(dir); 
IntPtr driver = LoadLibrary(dir + Path.DirectorySeparatorChar + "Driver.DLL"); 
IntPtr managed = LoadLibrary(dir + Path.DirectorySeparatorChar + "Managed.DLL"); 

和卸載序列

FreeLibrary(managed); 
FreeLibrary(driver); 

(還要注意的LoadLibraryFreeLibrary調用的順序)。