【问题标题】:LoadLibrary doesn't work when compiled to AnyCpuLoadLibrary 在编译到 AnyCpu 时不起作用
【发布时间】:2013-06-17 11:15:54
【问题描述】:

我正在开发一个从安装包中提取 cab 文件的 c# 应用程序。

为此,我使用LoadLibrary。这是 pinvoke C# 签名。

 [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
 internal static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);

上面的代码在编译工程到x86的时候可以正常工作,但是如果我编译到anycpu就失败了,最后一个win32错误是:

“%1 不是有效的 Win32 应用程序”

我尝试使用 IntPtr 插入字符串,也尝试使用不同的字符集,但没有任何效果。

【问题讨论】:

标签: c# pinvoke loadlibrary


【解决方案1】:

LoadLibrary 工作正常。问题是您试图将 32 位 DLL 加载到 64 位进程中。这是无法做到的,您引用的错误消息是尝试将模块与不匹配的位数混合的结果。

问题不在于LoadLibrary 的 p/invoke 签名,而是问题中未显示的对LoadLibrary 的调用。该调用导致尝试将 32 位 DLL 加载到您的 64 位进程中。除非您加载的所有本机 DLL 都是 64 位版本,否则您需要坚持使用 x86。

顺便说一句,在这个函数中使用CharSet.Ansi 真的没有意义。由于 .net 本身使用 UTF-16 文本,因此您最好使用 CharSet.Unicode,避免任何字符集转换并确保您的程序可以支持 Unicode 文件名。

更新

在 cmets 中,您询问是否可以从 64 位进程加载 32 位 DLL 以提取资源。这是可能的,但不是LoadLibrary。您需要通过LOAD_LIBRARY_AS_DATAFILE 调用LoadLibraryEx

【讨论】:

  • 谢谢,当我提出问题时,我认为问题出在签名上,但在查看错误代码后,我明白这是一个加载问题。你知道Kernel32有64位版本吗?
  • 我的错误 :) 问题是我尝试加载的 .exe 被编译为 32 位。
  • 正如我所说,问题不在LoadLibrary 的解决方案中。当然,kernel32 有一个 64 位版本,每个进程都包含它。对LoadLibrary 的调用正确。但是您尝试加载的模块,您传递给LoadLibrary 的模块的名称与您的托管进程的位数不匹配。
  • :(那么您知道如何在不使用 loadResource 的情况下提取 .exe 中的 cab 文件吗?
  • 我确实知道如何,并将其添加到答案中。我想我现在已经回答了你的两个问题。
猜你喜欢
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多