最近碰到了一個問題,要引入一個第三方的SDK,但是SDK中使用的一些dll和我原本程序里面有些dll是同名的,而且本程序的dll和sdk的dll名稱都不能修改。
解決這個問題,首先想到的就是多進程,這就用到了我們之前開發的一個專門用來托管dll的進程。先是將SDK打包到另外一個單獨的目錄(因為與本程序中的dll名稱沖突),隨后寫了一個包裝SDK的dll,把這個dll給了托管進程。
這樣既使用了SDK的功能,又把第三方的程序隔離開了,看似不錯的解決方案。
但是遇到了另外一個問題,我的托管進程也是在exe的目錄下的,所以他的默認加載順序還是exe所在路徑為最優先,這樣隱式加載還是會先加載該目錄下的同名dll,這樣會導致SDK所在的托管進程無法啟動。
所以再加一道程序: 在包裝SDK的dll工程里面設置要加載的SDK dll為延遲加載,然后在調用sdk方法前手動loadlibrary加載SDK的dll,這樣后面exe目錄下的同名dll就不會被加載了。
總結一下有一下幾點:
1. 隱式加載會按照標准順序加載,無法通過代碼修改加載順序
2. dll延遲加載,會在dll中導出方法第一次被調用的時候加載,所以在這之前有機會修改加載順序。
3. 除了LoadLibraryEx用LOAD_WITH_ALTERED_SEARCH_PATH這個參數加載dll之外,沒有其他方法可以影響exe目錄為最優先的順序(SetCurrentDirectory, SetDllDirectory)
4. 同名的dll只會被加載一次,只有所有加載同名的dll都會被忽略。所以利用這個特性,就可以做一些事情。比如延遲加載,先加載自己的,后面系統再去加載的時候發現已經加載了,后續的dll就不會被記載進來。
目錄結構如下: