【问题标题】:Unmanaged DLL is not loading with DLLImport C#未使用 DLLImport C# 加载非托管 DLL
【发布时间】:2013-11-26 05:43:04
【问题描述】:

我一定在这里遗漏了一些东西;快疯了.. 我正在使用 VS2010 C#,用 C# 开发一个 Windows 窗体应用程序。在同一个解决方案中,我有一个 c++ dll 项目,它将它的 DLL 输出到与 C# 可执行文件相同的“/bin/”文件夹。我正在查看文件夹,文件肯定在那里。我什至使用以下内容来确保它在运行时存在:

// yep.. it's there...
string s = System.IO.Directory.GetCurrentDirectory() + @"\Foo.dll";
System.Diagnostics.Debug.Assert(System.IO.File.Exists(s));

我的 DLL 有这个:

extern "C" __declspec(dllexport) int test_func();

我通过 DLL 资源管理器实用程序确认其中包含正确的名称。函数本身只做“return 4;”

C#代码是:

[DllImport("Foo.dll")]
private static extern int test_func();

我收到此错误:

.exe 中出现“System.DllNotFoundException”类型的未处理异常

附加信息:无法加载 DLL 'Foo.dll':对内存位置的访问无效。 (HRESULT 异常:0x800703E6)

【问题讨论】:

  • 你的应用是...32位还是64位?
  • 32 位。或者我应该说我没有明确定义 64 位应用程序。

标签: c# dll


【解决方案1】:

框架调用LoadLibrary时发生错误。这可以从错误信息中推断出来:

无法加载 DLL 'Foo.dll'

报告的错误代码是一个包含 Win32 错误代码 998 的 COM 错误代码,也就是 ERROR_NOACCESS。这里描述了导致调用LoadLibrary 并抛出ERROR_NOACCESS 的场景:http://support.microsoft.com/kb/196069

症状

LoadLibrary() API 有时可能会遇到访问冲突 在尝试将指定模块映射到 调用过程。在这种情况下,LoadLibrary() 返回值 NULL 和 GetLastError() 返回错误代码 998 (ERROR_NOACCESS)。 回到顶部 |提供反馈

原因

Windows NT 状态码 STATUS_ACCESS_VIOLATION 映射到 Win32 错误代码 ERROR_NOACCESS。因此,如果操作系统 加载程序遇到访问冲突(异常 C0000005),而 映射指定的DLL文件映像或执行启动代码, 加载程序会将最后一个错误设置为 998 (ERROR_NOACCESS) 并且 LoadLibrary() 函数将失败,返回值为 NULL。回到 顶部 |提供反馈

更多信息

当启动代码中的任何地方发生访问冲突时, 异常调度器检测是否遇到这个的进程 正在调试异常。如果是这样,第一次机会例外是 发送到调试器。

要解决 LoadLibrary() 故障,请在 调试器并为 C0000005 启用第一次机会异常处理 访问冲突异常。如果访问冲突发生时 LoadLibrary() 函数被调用,应用程序将进入 调试器。然后可以使用调试器的调用堆栈来跟踪 发生异常。堆栈跟踪应该可以帮助您缩小范围 与遇到的异常相关的实际问题。

有关如何启用首次机会异常处理的信息 C0000005 访问冲突异常,请参考调试器 文档。

本质上,您的 DLL 在其启动代码中产生了访问冲突。许多事情都可能导致这种情况,您需要对 DLL 进行一些调试。我建议您尝试从本机 C++ 主机调试它。以这种方式调试 DLL 可能会更容易。

顺便说一句,您的函数使用cdecl 调用约定,一旦您克服了当前的障碍,您需要修改您的C# p/invoke 以指定CallingConvention.Cdecl

【讨论】:

  • 我在我的 C# 应用程序中的 LoadLibrary 上使用了 DllImport[],并将其称为返回“0”。 ?!?我使用了与 File.Exists() 完全相同的路径,所以我认为这一定是某种权限问题..
  • 没有。它返回LoadLibrary 失败时返回0。这表明一个错误。如果您在LoadLibrary pinvoke 中包含SetLastError=true,您可以调用Marshal.GetLastWin32Error,它将返回998。这不是权限。您的 DLL 的 DllMain 正在引发访问冲突。你的下一步就是完全按照我说的去做。使用本机主机调试它。或者了解如何从 C# 主机启用非托管调试。
  • 哦,伙计,我没有看到这个……一个全局静态类正在访问它自己的“静态 std::map”成员。但它似乎是在成员的定义之前被访问的。我猜它不知何故没有及时初始化它自己的值以供构造函数使用。我什至不认为这是可能的!我重新排序了代码,现在它可以工作了……太疯狂了。
  • 是的。静态初始化。抓到你了!!
【解决方案2】:

假设你已经看过this link

您是否使用depends.exe 打开“foo.dll”以确保您满足所有依赖项?

【讨论】:

  • DLL 什么都不做。它仅取决于几个 stl 模板头。我运行了depends.exe,只得到了这个:错误:由于隐式依赖模块中缺少导出函数,至少一个模块具有未解析的导入。错误:发现具有不同 CPU 类型的模块。我猜它在抱怨是因为 DLL 是 32 位的,而且我运行的是 Windows 7 x64。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-17
  • 1970-01-01
相关资源
最近更新 更多