抑制“程序无法启动,因为缺少X.dll文件”错误弹出窗口

7
我有一个使用os.system来运行各种命令的Python程序。(它不能使用subprocess,因为它必须向后兼容到Python 2.0。)
在Windows上,有时命令会引用不寻常目录中的DLL文件,因此我会看到臭名昭著的“程序无法启动,因为X.dll丢失”错误弹出窗口。
我的问题并不是如何使命令找到它的所有DLL文件。我已经知道如何做到这一点。我想知道的是,如何告诉Windows当一个DLL文件丢失时“不要显示该对话框”。相反,子进程应该将错误消息打印到stderr(已在os.system调用中重定向到一个文件中)并退出失败(导致os.system返回一个错误代码)。这样我的程序就可以捕获错误并以自己的方式报告它,而不是等待某个人点击“确定”按钮。
MSDN通常是我的好帮手,但这一次我只得到了有关如何处理特定丢失DLL文件的建议,这很好,但不是我这次所需要的。
再次强调,这是一个极度向后兼容的情况:我需要一个适用于Python 2.7或所有早期版本,甚至追溯到2.0的解决方案。它还需要在所有流行的Windows版本(XP、Vista、7、8)上运行。与甚至更旧的Windows一起工作是非常可取的,但不是100%必需的。此外,第三方模块和帮助程序用任何其他语言编写都不是一个选项。(我想一个.BAT文件可以,如果那是唯一的方式的话。)

你能再解释一下吗?如果在这台机器上执行cl.exe而没有涉及Python,是否会出现相同的错误? - Krets
这可能取决于我选择了哪个 PATH 设置,也可能不会。但那不是问题的重点。我已经知道如何调整 PATH。问题是如何使错误报告给我的程序,而不是通过这个带外对话框。 - zwol
1个回答

12

使用SetErrorMode函数可以禁用调用进程的对话框。但需要阅读LoadLibrary文档才能发现“加载时缺少 DLL”符合SEM_FAILCRITICALERRORS覆盖的“关键错误”之一。

错误模式会继承到子进程,只要它们没有使用CREATE_DEFAULT_ERROR_MODE创建,CMD.EXE在创建子进程时似乎没有设置该标志。因此,在Python脚本启动时设置错误模式实际上可以抑制我所关心的情况下的对话框出现...

if sys.platform == 'win32':
    try:
        import ctypes
        # SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX
        ctypes.windll.kernel32.SetErrorMode(0x0001|0x0002|0x8000)
    except:
        pass

这不是最佳解决方案:子进程以特定错误代码(0xC0000135——实际上未记录为“缺少DLL”,但从搜索该数字时出现的情况来看,显然如此)终止,但详细信息(例如缺少哪个DLL)被忽略了。我仍然希望能找到某个设置,使加载器将详细信息报告给stderr。


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