2010-10-02 86 views
2

我在.net應用程序中使用了一個非託管庫,它在x86和64位系統上使用,因此編譯爲「任何CPU」。然而,非託管的本地.dll有兩個不同的.dll文件(一個用於win32,另一個用於x64)。如何根據CPU架構使用正確的非託管.dll?

是否有任何方法仍然保留'任何CPU'/一種二進制方式與不同的本地.dll有關的x86/64/64位系統的P/Invoke簽名?或者 - 是唯一的方法來創建單獨的配置&因此分佈?如果是這樣,是否有任何編譯#if /#endif標誌我可以用它?

回答

0

我會把p/invoke代碼放到一個單獨的程序集中(一個用於32,另一個用於64位),然後根據平臺的不同,將load the appropriate one at run time

有很多方法可以確定系統的類型。 Lots are documented here

+0

謝謝......!我會用這個 - 我通過我的待辦事項列表中的MEF有適當的可擴展性(而且我很沮喪,我沒有想過這個問題,然後再問..哦,我的)。所以我將使用MEF,並且無論如何我必須處理BadImageFormatExceptions,以防嚴格地將x86或x64擴展程序集加載到「相反」系統上。 – 2010-10-03 11:12:12

0

您可以手動呼叫LoadLbrary & GetProcAddress,通過調用Marshal.GetDelegateForFunctionPointer(procAddress, delegateType)將函數指針轉換爲代表。這會產生更多的代碼,但可以讓您將所有interop代碼保存在一個程序集中。例如,NHanspell使用這種方法。

1

在您的bin文件夾中,您可以添加另外兩個名爲x86x64的文件夾。這些文件夾將包含本機DLL的x64和x86映像。
在啓動時(應用程序加載任何外部DLL之前),您可以使用環境變量modifyprocess'sPATH環境變量,因此它將根據進程的位數包含相應的子目錄(IntPtr.Size應指示您的位數)。

對於託管的DLL探測,您可以訂閱AppDomain.AssemblyResolve事件,因此您可以自己從正確的子目錄加載程序集(例如,通過使用Assembly.Load)。

+0

+ 1,修改PATH是一個有趣的方法,但它是相當重要的,它只能完成一次和啓動EXE。 Pinvoking SetDllDirectory()是另一種方式,但如果非託管代碼也使用它,那麼它也可能具有(罕見)失敗模式。將其作爲部署任務或者僅僅強制實施平臺目標都是風險較小的解決方案。 – 2010-10-02 13:23:30