为啥 %1 很少被替换为“%1 不是有效的 Win32 应用程序”。

Posted

技术标签:

【中文标题】为啥 %1 很少被替换为“%1 不是有效的 Win32 应用程序”。【英文标题】:Why is %1 rarely substituted in "%1 is not a valid Win32 application."为什么 %1 很少被替换为“%1 不是有效的 Win32 应用程序”。 【发布时间】:2017-09-22 17:32:46 【问题描述】:

我相信大多数 Windows 开发人员都熟悉此错误消息,通常是在尝试混合 32 位和 64 位可执行文件时。特别是 Python 和 Java 都可以搞定。

%1 is not a valid Win32 application.

很明显%1 代表失败命令的第一个参数 - 即尝试加载的可执行文件 - 但为什么它没有填写实际路径?

是调用者做错了什么,还是出于兼容性原因无法修复的某些 Windows 子系统的基本故障?

【问题讨论】:

您是否有特定的情况可以向我们指出会产生错误的情况?我不能说我见过它。 查看“相关”列表或直接搜索它 -> @MarkRansom 最近让我很恼火的两个涉及加载一个使用错误架构构建的本机 Python 模块,以及一个 Apache 项目在 64-位 JVM。 【参考方案1】:

错误消息来自 Windows 本身,您可以在System Error Codes (0-499) 看到完整列表。您可以使用 FormatMessage 将 API 返回的错误代码转换为消息,该消息具有可选的 Arguments 数组;消息中的任何%1 都将替换为此数组中的第一个元素。如果没有为参数传递任何内容,如果使用了 FORMAT_MESSAGE_IGNORE_INSERTS 标志,%1 将保持不变,否则 FormatMessage 将失败(感谢 IInspectable 提供的信息)。

作为一个可能会遗漏的示例,请考虑错误代码立即转换为异常的代码。如果异常包含错误代码但没有其他内容,则没有上下文可以知道将什么传递给FormatMessage

【讨论】:

所以基本上是成千上万的 Windows 开发人员没有正确格式化错误消息? 即将发布此答案,并同意您之前的评论,尽管我做了很多 Windows 开发,但我从未见过此消息。你必须做错事才能看到它。这不是 Windows 子系统的故障。 @OrangeDog 完全正确。你应该从失败的系统调用的上下文中知道你需要传递什么参数,但由于它是可选的,它要么会被错过,要么会在上下文丢失的地方被调用。 @CodyGray 问题不是你为什么会收到错误,而是为什么它很少告诉你路径是什么 是的,我相信我理解了这个问题。您问,“是调用者做错了什么,还是某些 Windows 子系统因兼容性原因无法修复的基本故障?”,我说的是前者,而不是后者。 @橙色【参考方案2】:

调用者做的一切都是正确的。他们打电话给FormatMessage,传递FORMAT_MESSAGE_IGNORE_INSERTS 标志1),就像每个人都应该这样做的。调用者无法控制所创建的消息,也无法知道它应该传递额外的参数、它们应该是什么类型或有多少。

这是 Windows 错误报告系统中的一个早期设计错误,您会在每个表现良好的应用程序中看到这些占位符。


1)见The importance of the FORMAT_MESSAGE_IGNORE_INSERTS flag。

【讨论】:

FORMAT_MESSAGE_IGNORE_INSERTS 标志被记录为:“消息定义中的插入序列将被忽略并原封不动地传递到输出缓冲区。此标志对于获取消息以供以后格式化很有用。”这似乎与您的回答不一致。因此,要么他们已经记录了您所谓的“早期设计错误”,要么该标志仅用于推迟格式。 @IInspectable 大概你应该将相同的参数传递给刚刚失败的函数。 我认为期望是调用者为每个 expected 错误执行特定的case 并添加所需的插入参数。对于default 案例,当然传递FORMAT_MESSAGE_IGNORE_INSERTS 如果您刚刚执行了可能以这种特定方式失败的 API 调用,您需要检查错误代码并提供参数。我猜这并不完全不寻常,例如,如果您正在加载用户提供的插件,或者您是代表您正在运行的代码加载 DLL 的解释器,您应该考虑到这一点,但事实并非如此就像您每次处理 Win32 错误时都需要这样做。 @HarryJohnston:FormatMessage 返回的消息不在您的控制范围内。您无法在系统中查询占位符变量的计数、类型和语义。如果您建议在代码中的某个位置过滤掉 一个 单个错误代码,以得到错误消息 “foo.dll 不是有效的 Win32 应用程序”。 那么您不妨自己动手,并生成一个真正 有用的错误消息(您精心设计的错误消息肯定不是)。没有什么与声明相矛盾,即 API 的设计被破坏,或证明投反对票是合理的。

以上是关于为啥 %1 很少被替换为“%1 不是有效的 Win32 应用程序”。的主要内容,如果未能解决你的问题,请参考以下文章

如何解决“%1 不是有效的 Win32 应用程序”?

为啥在使用 wprintf 时 ©(版权符号)被替换为 (C)?

DBeaver执行sql脚本报错:CreateProcess error=193, %1 不是有效的 Win32 应用程序。

DBeaver执行sql脚本报错:CreateProcess error=193, %1 不是有效的 Win32 应用程序。

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

为啥 Hashmap 值在使用重复键时被替换,即使它在内部为每个存储桶使用链表? [复制]