2010-10-02 82 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