Python脚本转exe后出现ImportError:导入win32gui时DLL加载失败
问题
我编写了一款可修改系统光标的Python脚本,直接运行.py文件时一切正常,但打包为exe文件后运行,出现如下错误:
ImportError: DLL load failed while importing win32gui: Die angegebene Prozedur wurde nicht gefunden
(德语翻译:导入win32gui时DLL加载失败:找不到指定的程序)
我能理解是程序无法找到win32gui相关依赖,但为什么win32con能成功导入呢?以下是我的代码:
import ctypes from time import sleep import win32con import win32gui import os, sys def resource_path(relative_path): try: base_path = sys._MEIPASS except Exception: base_path = os.path.abspath(".") return os.path.join(base_path, relative_path) path = resource_path("./test.cur") sleeptime = 30 cursor_value = { 32650: "OCR_APPSTARTING", 32512: "OCR_NORMAL", 32515: "OCR_CROSS", 32649: "OCR_HAND", 32651: "OCR_HELP", 32513: "OCR_IBEAM", 32648: "OCR_NO", 32646: "OCR_SIZEALL", 32643: "OCR_SIZENESW", 32645: "OCR_SIZENS", 32642: "OCR_SIZENWSE", 32644: "OCR_SIZEWE", 32516: "OCR_UP", 32514: "OCR_WAIT" } original_cursor = {} def load_original_cursor(Values): for k, v in Values.items(): hold = win32gui.LoadImage(0, k, win32con.IMAGE_CURSOR, 0, 0, win32con.LR_SHARED) hsave = ctypes.windll.user32.CopyImage(hold, win32con.IMAGE_CURSOR, 0, 0, win32con.LR_COPYFROMRESOURCE) original_cursor[k] = hsave print(original_cursor) def set_fake_cursor(path, Values): for k, v in Values.items(): hnew = win32gui.LoadImage(0, path, win32con.IMAGE_CURSOR, 0, 0, win32con.LR_LOADFROMFILE) ctypes.windll.user32.SetSystemCursor(hnew, k) def set_original_cursor(Original_Values): for k, v in Original_Values.items(): ctypes.windll.user32.SetSystemCursor(v, k) if __name__ == "__main__": load_original_cursor(cursor_value) set_fake_cursor(path, cursor_value) sleep(sleeptime) set_original_cursor(original_cursor) sys.exit(-1)
解决方案
原因分析
win32con和win32gui的导入逻辑本质不同:
- win32con是纯常量定义模块,仅包含Windows API的常量映射,不需要依赖外部DLL就能完成导入,打包时会被直接包含进exe。
- win32gui是Windows GUI API封装模块,依赖
pywin32_system32目录下的pywintypesXX.dll、pythoncomXX.dll等系统级DLL,打包工具(如PyInstaller)默认可能未正确收集这些依赖,或打包后DLL加载路径异常。
修复步骤
重装并注册pywin32
先卸载旧版本,再安装适配当前Python版本的最新版:pip uninstall pywin32 -y pip install pywin32 --upgrade安装完成后必须执行注册脚本,确保系统DLL被正确识别:
python -m pywin32_postinstall.py -install调整PyInstaller打包参数
打包时显式指定依赖,强制收集pywin32相关文件:# 基础打包命令,强制导入win32gui依赖 pyinstaller --onefile --hidden-import win32gui your_script.py # 若仍有问题,添加全量收集参数 pyinstaller --onefile --collect-all pywin32 your_script.py用ctypes替代win32gui调用(可选)
既然已使用ctypes调用user32.dll,可直接替换win32gui的LoadImage方法,彻底规避pywin32的打包问题:# 替换win32gui.LoadImage的ctypes实现 user32 = ctypes.windll.user32 user32.LoadImageW.argtypes = [ctypes.c_void_p, ctypes.c_wchar_p, ctypes.c_uint, ctypes.c_int, ctypes.c_int, ctypes.c_uint] user32.LoadImageW.restype = ctypes.c_void_p # 加载系统光标 hold = user32.LoadImageW(0, k, win32con.IMAGE_CURSOR, 0, 0, win32con.LR_SHARED) # 加载自定义光标 hnew = user32.LoadImageW(0, path, win32con.IMAGE_CURSOR, 0, 0, win32con.LR_LOADFROMFILE)
验证方式
打包完成后,若为非单文件打包,检查exe目录是否包含pywintypesXX.dll和pythoncomXX.dll;运行exe后观察是否仍出现DLL加载错误。
内容的提问来源于stack exchange,提问作者Drip Narix
相关产品推荐
相关产品推荐

