Ctypes throws "WindowsError: [Error 193] %1 is not a valid Win32 application", but it's not a 32/64-bit issue

Ctypes throws "WindowsError: [Error 193] %1 is not a valid Win32 application", but it's not a 32/64-bit issue

我在 Ctypes 中加载 Windows DLL 时遇到问题,这引发了错误:

WindowsError: [Error 193] %1 is not a valid Win32 application

在我的例子中,它是一个用 VS2012 在 Windows 7 64 位上构建的 32 位 DLL,在我的开发机器上我可以很好地加载它。我检查它是 32 位的,使用 dumpbin /headers:

FILE HEADER VALUES
         14C machine (x86)

当我尝试在生产 VM 上通过 Ctypes 加载相同的 DLL 时出现问题,它也是 Windows 7 64 位。我正在做的是:

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

对于其他问题,我已经尝试了几件事。

该错误非常笼统,相当神秘。由于它在相同的 Python 环境中的开发机器上工作,我假设它与一些只有 Visual Studio 安装才能给我的依赖关系有关?

如何正确解决此问题?

@eryksun 评论道:

Run under a debugger such as cdb or windbg. Call windll.kernel32.DebugBreak() just before calling CDLL(dllabspath). Set a breakpoint on kernelbase!LoadLibraryExW and resume the thread via g. When it breaks back into the debugger enter pt to execute up to the function return. Then enter !teb to check the LastStatusValue for the thread. This NT status value may be of more help.

进一步:

If you prefer to keep the system as clean as possible, try the following: windll.kernelbase.LoadLibraryExW(c_wchar_p(dllabspath), None, 0); status = windll.ntdll.RtlGetLastNtStatus().

Otherwise it requires installing the debugging tools from the SDK. Symbols can be downloaded on demand from Microsoft's symbol server by setting the environment variable _NT_SYMBOL_PATH=symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols, which caches symbols in C:\Symbols

调试时,这可能会有所帮助:

There are several status codes that produce Win32 error ERROR_BAD_EXE_FORMAT (193). In your case it's STATUS_INVALID_IMAGE_FORMAT (0xC000007B). Possibly in the production VM one of the dependent DLLs that it tries to load is 64-bit. At the breakpoint enter du poi(@esp+4) to print the first argument, which is the unicode path of the DLL it's attempting to load. Also check the stack trace via kc.

使用这个提示,我发现了对 64 位 WinPCAP DLL 的依赖。使用 DependencyWalker 检查所有内容,它在两台机器上看起来都一样,抱怨 64 位依赖,但显然在新机器上,DLL 加载路径不同 它永远找不到 32 位版本。