Win 7 DllImport C#出现奇怪错误,无效的内存访问位置?

8
我正在使用DllImport从我的C#应用程序访问C++ dll中的一些函数。
这段代码在我的开发笔记本电脑上运行良好,它是Windows 7 64位系统,dll本身是32位的,所以我在32位下运行托管dll的进程,它可以正常工作。然而,当我尝试在目标机器上运行完全相同的进程时,它会出现“无效的内存位置访问”的错误。
我不确定问题出在哪里,我已经查看了许多网络资源,但没有一个解决了我的问题。我不明白为什么它在我的开发机上运行良好,但在目标机上却不行?
dll本身没有问题,与dll一起提供的示例在我的目标机上都能正常工作(这是使用DllImport的C#应用程序)。
有人遇到过这个问题吗?我已经为此奋斗了两天!
异常:{"Unable to load DLL 'CLEyeMulticam.dll': Invalid access to memory location. (Exception from HRESULT: 0x800703E6)"}

DEP在我的开发计算机上是OptIn(基本上是启用DEP)。但这完全没有问题...我一直在尝试找到任何差异,但我使用相同的ISO设置了两台机器,都使用VS2010,Robotics Framework RC3和我正在尝试访问的相同DLL。但无论我怎么尝试,我都无法让这台新机器正确读取机器人框架中的DLL!! - James
我也尝试过完全重新格式化机器,但仍然存在相同的问题。 - James
你能启用非托管调试(或使用非托管调试器,如WinDbg),并找出它实际崩溃的位置吗? - Will Dean
我无法解决这个问题。它只在使用Microsoft Robots Studio中的dll时发生。最终,我不得不创建一个新的应用程序来托管dll,并通过WCF命名管道进行跨进程通信 :( - James
10个回答

1

1
动态链接库(DLL)可能因为未解决的依赖关系而崩溃,在目标机器上使用Dependency Walker打开你的DLL,查看是否有问题。

在这种情况下,“Invalid access to memory location”错误是否会导致程序崩溃? - Pupsik

1

我注意到你的开发机和目标机器之间有一个很大的区别,那就是开发环境。确保在目标机器上安装了所有必要的可再分发组件。

编辑:我曾经遇到过类似的问题,当一些dll编译成不同版本的.Net框架或者使用不同版本的Visual Studio制作时,由于每个版本的可再分发组件不同,最新的可再分发组件并不完全向后兼容。


0

如果您在C#应用程序中遇到此错误,通常表示本机代码对内存进行了一些不好的操作,而ILM可以看到 - 请检查您的DllMain例程中/调用的代码 - 在您的调用实际通过之前调用 - 如果它表现不良,您将看到此结果。


0

我以前遇到过这个问题。我认为你的问题是VS尝试打开文件但没有读取权限。您需要确保您正在使用的帐户可以访问DLL。尝试禁用UAC以查看是否有效,或使用管理员帐户。或者尝试将DLL上的完全控制授予所有人

编辑:您能否以管理员身份运行VS(右键单击 ->以管理员身份运行)?您能否将DLL放在桌面上尝试?您的工作计算机和失败计算机之间是否存在文件夹结构差异?此外,如果您在VS之外执行它,DLL是否可以正常运行(也尝试以管理员身份运行它)?

希望对您有所帮助


是的,文件夹是一样的。我正在尝试运行的进程名为DssHost.exe,它是Microsoft Robotics Studio的一部分。它位于C:\Robotics\Bin\DssHost.exe,与我的dll 'CLEyeMulticam.dll'一起(两台计算机上都是相同的)。DssHost使用我在VS中编写并部署到C:\Robotics\Bin\的.NET dll(PS3WebcamService.dll),将其加载到DssHost中并运行它。只有在我的原始开发框中才能正常工作,其他新框会报告上述错误。但是我的开发框已经启用了DEP?(但UAC已关闭。) 继续.... - James
如果我尝试通过单独的.NET Windows表单应用程序运行与我的.NET dll中相同的代码,则在两台计算机上都可以正常工作。我不明白我的.NET Windows应用程序和托管服务dll的.net DssHost之间的区别,以及为什么它只影响第二台计算机。附注-我知道这很淘气,但我总是以管理员身份运行VS。从Admin Cmd行启动DssHost会给我带来相同的错误。感谢您的帮助 :) - James
我真的被这个问题难住了。希望其他人能给你一些见解! - TheCloudlessSky
我现在和詹姆斯处于同样的情况。这是我的情况:http://stackoverflow.com/questions/5375675/native-loading-works-good-loading-from-net-gives-error-unable-to-load-dll-my-d - Alex Blokha

0

我以前遇到过类似的问题,可以尝试以下方法:

  • 检查 .NET CLR 版本。目标环境中是否存在开发环境中没有的 SPs/KBs?
  • 尝试加载 C++ DLL 的调试版本。能否成功加载?如果失败,建议在目标环境下使用 WinDBG 启动应用程序。一旦出现异常,简单的 !analyze -v 命令将提供大量信息。
  • 作为下一步,我建议在单元测试环境中重现此问题。你提到的 C# 示例是否构建为 x64 VM?如果没有,请尝试这样做,并尝试在目标环境中运行生成的示例二进制文件。问题是否可重现?

0

我遇到了一个问题,64位的.NET应用程序(“Any CPU”)试图加载32位本地DLL依赖项。我没有错误消息在我面前,所以我不能告诉你是否是同样的问题。我的问题的解决方案是将我的构建更改为仅限x86。

如果DLL的位大小在每个框上都在变化,也许存在结构大小差异,因此您的PInvoke签名变得不正确。这很容易导致缓冲区溢出,并导致本地代码中的堆栈损坏。


0

@Merlyn Morgan-Graham 我们遇到了类似的问题。我们使用“任何 CPU”构建生成了 .Net 应用程序,并尝试在 32 位 C++ Dll 中使用。当我们在 64 位操作系统上运行 .Net 应用程序时,它作为 64 位可执行文件运行,因此出现了类似的问题。在 X86 构建中构建后,对 C++ Dll 的调用完全正常。还有一件重要的事情是,如果您在 .Net 代码中使用 C++ DLL,则会有相当数量的 marshalling,因此重要的是坚持构建类型(即 X86、任何 CPU 或 X64)。

请还要检查以下链接: Windows Vista:无法加载 DLL 'x.dll':内存位置访问无效。(DllNotFoundException)


0
显而易见,但可能很糟糕的解决方案是明确为32位构建C#端。检查如何通过编程或填充注册表键创建进程外宿主,或者在其他框中设置为创建64位托管进程或尝试进程内调用,这意味着加载...如果它是一个注册表设置,请不要忘记对于混合23/64位情况,有两个分支要挖掘。

-2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接