使用 DLLImport 找不到非托管 DLL
Posted
技术标签:
【中文标题】使用 DLLImport 找不到非托管 DLL【英文标题】:Can't find unmanaged DLL using DLLImport 【发布时间】:2017-08-05 02:36:24 【问题描述】:以上是我的文件夹结构。我有一个 Cordova 应用程序和一个 Windows 运行时组件 - IBscanUltimate。包含文件夹具有调用非托管 IBscanUltimate.dll 的 C# 代码。 Class1.cs是这样的:
using System;
namespace IBscanUltimate
public sealed class Class1
public static String getSDK()
IBscanUltimate.DLL.IBSU_SdkVersion a = new DLL.IBSU_SdkVersion();
IBscanUltimate.DLL._IBSU_GetSDKVersion(ref a);
return "SDKVersion: " + a;
IBScanUltimateApi.cs 和 _IBSU_GetSDKVersion 看起来像这样:
internal partial class DLL
[DllImport("IBScanUltimate.DLL")]
private static extern int IBSU_GetSDKVersion(ref IBSU_SdkVersion pVerinfo);
public static int _IBSU_GetSDKVersion(ref IBSU_SdkVersion pVerinfo)
int nRc = IBSU_STATUS_OK;
nRc = IBSU_GetSDKVersion(ref pVerinfo);
return nRc;
我已将 DLL 放置在许多位置以查看它是否会被拾取,并且它们都具有上述属性。但是当我尝试运行我的应用程序时,它说无法找到 IBScanUltimate.DLL
输出是这样的:
我不确定我做错了什么以及为什么 DLLImport 找不到我的 dll。感谢您的帮助。
确切的错误是:
System.DllNotFoundException: Unable to load DLL 'IBScanUltimate.DLL': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
更新 #1:
我遇到过https://msdn.microsoft.com/en-us/library/windows/desktop/hh447159(v=vs.85).aspx 这篇文章是解释LoadPackagedLibrary
函数可以用来加载dll。我没有看到任何关于如何在 C# 中使用它的示例。
更新 #2:
Specify the search path for DllImport in .NET 提到可以使用SetDllDirectory
或AddDllDirectory
。他有一个SetDllDirectory
的代码 sn-p,但参数是 string[] paths
。我将如何指定相对参数?
更新 #3:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);
public static bool setPath(String path)
//Windows.Storage.
//return SetDllDirectory("ms-appx:///");
return SetDllDirectory(path);
我尝试使用我的应用程序应该可以访问的多个位置调用 SetDllDirectory(path)
方法,但我一直在“错误”。我尝试过的几个例子:
NativeMethods.setPath(Package.Current.InstalledLocation.Path.ToString());
StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFolder folder = Windows.Storage.KnownFolders.MusicLibrary;
这是我的应用程序的安装位置:
C:\Users\AAA\App\hello\platforms\windows\build\windows\Debug\x64\AppX
我可以看到我的 DLL 在那里。但是我仍然遇到无法找到 DLL 的异常。我必须在清单上写一些关于这个的东西吗?
更新 #4: 我在 DLL 上运行了一个 dumpbin,我在 dumpbin 中看到了以下 DLL:
WINUSB.DLL
mfc90.dll
MSVCR90.dll
KERNEL32.dll
USER32.dll
GDI32.dll
VERSION.dll
MSVCP90.dll
SETUPAPI.dll
我想我想分别检查上面的每个 dll,看看我的 Windows 运行时是否可以选择它?其中之一可能是未加载的罪魁祸首?
更新 #5: 在看到 Peter Torr - MSFT 的答案并在 Google 上搜索 MFC 后,我发现了这篇文章 https://msdn.microsoft.com/en-us/library/d06h2x6e.aspx,其中指出:
The MFC classes and their members cannot be used in applications that execute in the Windows Runtime.
我想现在结束这场疯狂的狩猎。我将关闭它,因为我尝试加载的库依赖于 Windows 运行时不可用的库。 我有这种感觉,因为 Windows 窗体应用程序会运行,但转换为 Windows 运行时的代码会给出找不到 DLL 的错误。感谢彼得指导正确的方向。
【问题讨论】:
更改了 C# 项目。我不明白你关于文件名的问题。如果这是您想要的,我也粘贴了属性屏幕截图。它仍然给我同样的错误;找不到 DLL。 你说的是关闭的项目:IBscanUltimateWRT? 看到您关于名称冲突的评论后,我摆脱了该项目,创建了一个名为 IBsWRT 的新 Windows 运行时项目。 @Norman:你捕获了“devenv.exe”。那不是你的应用程序,那是 Visual Studio。抱歉,我帮不了你。 @Noman 你检查过这些链接吗 - ***.com/questions/28620082/… ***.com/questions/39626809/… 【参考方案1】:您尝试加载的 DLL 显然是为桌面应用程序构建的(它具有用户、GDI 和 MFC 导入),并且不能作为 UWP 二进制文件工作。我还怀疑 DLL 没有设置 AppContainer 标志(您传递给链接器的选项)。您将需要找到另一种方法来完成您的需求(如有必要,请通过the Windows Platform UserVoice 提出任何功能请求。
【讨论】:
所以我不能在windows应用商店使用这个DLL?但是User.dll我已经可以使用了。为什么我不能使用其他的? 支持少数 User32 API(处理鼠标和键盘输入),但大多数不支持。即使它们今天“工作”,它们将来也可能会中断 - 如果您尝试使用预先构建的边界,请务必在您的应用上运行 WACK 工具。【参考方案2】:我怀疑它可以很好地找到您的 DLL,但它无法找到它的一个或多个依赖项。不幸的是,这两种情况都会导致非常通用的 DllNotFoundException,它提到了您尝试 P/Invoke 到的 DLL。
有一种简单的方法可以找出缺少的内容! Windows 包含一个称为“加载程序快照”的功能,当启用该功能时,它将记录 Windows DLL 加载程序为您的进程所做的所有事情。这意味着它还将打印它无法加载的 DLL。要启用它,请在管理员命令提示符下运行:
gflags.exe -i "<executableName>.exe" +sls
其中可执行文件名称只是您的可执行文件的名称,不包括文件夹。要查看输出,您还需要启用本机或混合模式调试器。您可以在 Visual Studio 的项目属性调试选项卡中执行此操作。
您可以在此处阅读有关加载快照的更多信息:
https://blogs.msdn.microsoft.com/junfeng/2006/11/20/debugging-loadlibrary-failures/
【讨论】:
但是我有一个 .appx 包。我将如何在 .appx 上使用它? .appx 包最终仍然包含一个可执行文件。它可能会匹配您的主要项目名称。 不,.appx 不是“完全”一个 exe 文件。或者更确切地说,我不确定如何在 .appx 上执行 glfags,它给出的错误是它无法在 .appx 上执行 gflags。 .appx 只是一个稍作修改的 zip 文件。里面有一个.exe文件。你在那个 .exe 文件上启用 gflags,而不是在 .appx 上。 不,.appx里面没有.exe文件。以上是关于使用 DLLImport 找不到非托管 DLL的主要内容,如果未能解决你的问题,请参考以下文章