无法在Windows Mobile中找到PInvoke DLL错误

12

我在Windows Mobile 5.0模拟器上遇到了很多麻烦,无法让基本场景正常运行。我的WinForms应用程序最终会调用本地代码。部署工作正常,并且所有本地DLL都被复制到与WinForms .exe相同的文件夹中。我还使用远程文件查看器工具验证了这一点。

然而,当我启动我的应用程序时,它总是失败并显示“找不到PInvoke dll - System.MissingMethodException”错误(当调用本地代码时,DllImport属性变得无用)。 我知道本地dll在可执行文件的同一个文件夹中被找到。我还需要做什么?

我正在使用VS 2008。


2个快速注释: 1)第一次我没有在exe文件夹中拥有任何本地DLL。所以这个异常至少当时是有意义的。现在已经确保部署了所有东西,我怎么会再次遇到相同的异常呢? 2)我尝试按照此帖子中描述的方式设置日志记录:http://blogs.msdn.com/netcfteam/archive/2005/07/24/442609.aspx 我使用远程注册表编辑器进行设置,但无济于事。根本没有创建任何日志文件!为什么这么多基本的东西都会出错呢? - Dilip
4个回答

9
为了补充Jared的回答,以下是在CF中使用P/Invoke时出现MissingMethodException的另外四个常见原因:
3. 您缺少调用的本地库的依赖项。 4. 本地程序集被编译为错误的子系统(即桌面而不是CE)。 5. 本地程序集被编译为错误的处理器(即x86而不是ARM)。 6. 没有足够的虚拟内存来加载DLL。
您是否确认DLL入口点未使用任何修饰符,例如dumpbin

此外,如果您期望本地 DLL 与调用 exe 在同一目录中,请确保 exe 实际上已部署在相同的目录中。 - Hawkez

5

根据错误信息,通常有两个问题:

  1. 无法找到 DLL。DLL 是通过查找执行目录和 PATH 环境变量来找到的。
  2. 无法在 DLL 中找到函数。您是否检查过 DLL 的声明和定义都是 extern "C" 并标记为 __declspec(dllexport)

此外,进行合理性检查以确保 DLL 名称拼写正确且不缺少 .dll 后缀。


嗨,贾里德 感谢您的回复。 1)我非常确定本地dll与执行应用程序位于同一目录中。实际上有两个本地dll。我注释了对其中一个的调用,现在另一个正在抛出相同的异常。 2)请检查-我已经为Win32平台编译了相同的代码库,并且在那里它可以正常工作。dll名称拼写正确,并且确实具有.dll后缀(这不是您的意思吗?) - Dilip
你知道为什么我无法正确设置这个吗:http://blogs.msdn.com/netcfteam/archive/2005/07/24/442609.aspx?我使用了远程注册表编辑器来输入所有必需的键,但日志文件仍未被创建。今天似乎是万事不顺的一天! - Dilip
请注意,无论是否带有“dll”后缀,它都可以正常工作,但您应该在传递的确切字符串中保持一致(我使用const):http://www.danielmoth.com/Blog/2007/12/be-consistent-with-dllimports.html - ctacke
到目前为止,所有的建议都是我过去解决这些问题所使用的。不过我有两个尝试的方法。1.启用.NETCF日志记录,尝试在最后一个键和键值下设置DWORD值。我忘记了哪种组合对我有效,但我记得它让我感到困惑,现在仍然如此 - 例如[HKLM\Software\Microsoft.NETCompactFramework\Diagnostics\Logging] "Enabled" = 1。2.尝试使用已发布编译版本的本机DLL。我们有一些DLL拒绝P/Invoke其调试版本。从未解决过,可能是构建开关的问题。 - Damon8or

0

你的问题是由于WM5内存管理很糟糕。DLL从插槽顶部加载到底部,而应用程序从底部加载到顶部。如果你的应用程序和DLL之间没有足够的空间,你将收到“无法调用”错误。

WM5为应用程序分配了32个32Mb的插槽。

每次WM5为DLL分配内存时,它使用至少64Kb的块,因此如果你的DLL是32K,它将占用64k,如果你的DLL占用68k,则WM5将分配2x64Kb-128Kb。

当WM5加载所需的DLL时,它将始终在先前加载的应用程序的底部地址加载,即如果应用程序1已加载2×30kb的DLL,则第一个DLL将加载在地址0到64k,第二个DLL将加载在64到128,然后你的应用程序将从128kb加载其DLL,即使你的应用程序运行在单独的插槽中。

为了使事情正常工作,你需要尽早加载你的应用程序或从Windows启动文件夹中删除不需要的应用程序。


1
真的,但不是真的。对于本地DLL是真的,但对于这个问题来说却不是。这个问题被标记为“紧凑框架”,托管的DLL不会在这种内存模型下加载。它们作为内存映射文件加载,并且不占用64k虚拟内存块。MSDN有一个非常好的网络研讨会,介绍了紧凑框架如何使用内存,你可能会感兴趣。 - ctacke

-1
你所使用的 DLL 没有定义你所调用的方法,因此出现了异常。它可以编译通过,但在运行时会出现问题。解决方案是确保该定义是否存在于 DLL 中,否则你需要选择其他的 DLL。

该方法不得用于导出目的。 - Naruto

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