我在Ctypes中加载Windows DLL时遇到问题,这会引发错误:
WindowsError: [Error 193] %1 is not a valid Win32 application
就我而言,它是在Windows 7 64位上使用VS2012构建的32位DLL,在我的开发机器上我可以加载它。我使用dumpbin /headers
检查了它的32位:
FILE HEADER VALUES
14C machine (x86)
当我尝试在生产VM(也是Windows 7 64位)上通过Ctypes加载相同的DLL时,会出现问题。我正在做的是:
from ctypes import *
self.dll = CDLL(dllabspath)
我明白了:
File "C:\Users\user\Desktop\WinPython-32bit-2.7.10.1\.....\__init__.py", line 365, in __init__
self._handle = _dlopen(self._name, mode)
WindowsError: [Error 193] %1 is not a valid Win32 application
从其他问题我已经尝试了几件事。
This,this,this和this问题表明我的环境必须相同,即32位Python,32位DLL 。这是我的开发系统和VM I测试的情况。在这两者上,我使用的是WinPython 32位最新版本。它适用于开发机器,它在VM上失败。
Here,它与g ++和旧的Visual Studio运行时相关。我用VS2012编译了一切,所以我认为这不适用于此。对需要MSVCR80.dll
的第三方库存在延迟加载的依赖关系,但它已延迟加载且从未调用过。
我还在目标计算机上安装了Visual C ++ 32位运行时。
This表明DLL需要导出一个C接口。
我知道DLL的文件路径/文件名是正确的,和以前一样,存在丢失DLL依赖项的问题,我得到了一个Windows弹出窗口。现在已经不见了。
错误非常通用,相当神秘。由于它在同一个Python环境中的dev机器上工作,我假设它与某些只有Visual Studio安装可以提供给我的依赖关系有关吗?
如何正确排除故障?
答案 0 :(得分:0)
@eryksun评论:
在诸如
cdb
或windbg
之类的调试器下运行。致电windll.kernel32.DebugBreak()
之前先致电CDLL(dllabspath)
。在kernelbase!LoadLibraryExW
上设置断点,然后通过g
恢复线程。当它重新进入调试器时,请输入pt
以执行直至函数返回。然后输入!teb
,以检查LastStatusValue
中的线程。此NT状态值可能会有更多帮助。
进一步:
如果您希望保持系统尽可能清洁,请尝试以下操作:
windll.kernelbase.LoadLibraryExW(c_wchar_p(dllabspath), None, 0); status = windll.ntdll.RtlGetLastNtStatus().
否则,它需要从SDK安装调试工具。可以通过设置环境变量
中_NT_SYMBOL_PATH=symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols
从Microsoft的符号服务器中按需下载符号,该环境变量将符号缓存在C:\Symbols
调试时,这可能会有所帮助:
有几种状态代码会产生Win32错误
ERROR_BAD_EXE_FORMAT
(193)。您的情况是STATUS_INVALID_IMAGE_FORMAT
(0xC000007B
)。在生产VM中,它可能尝试加载的依赖DLL之一可能是64位。在断点处输入du poi(@esp+4)
以打印第一个参数,这是它尝试加载的DLL的unicode路径。还要通过kc
检查堆栈跟踪。
使用此提示,我发现了对64位WinPCAP DLL的依赖性。使用 DependencyWalker 进行的所有操作在两台计算机上看起来都一样,抱怨有64位的依赖关系,但显然在新计算机上, DLL加载路径不同,并且它永远找不到32位版本。