CreateProcess和带空格路径:微软为了掩盖程序猿的错误,真是煞费苦心啊

@Ta 2020-10-29发布,2020-10-29修改 12974点击

背景

我有程序A和程序B,两个都是Windows程序。程序A启动后会调用Windows API CreateProcess 启动程序B。

现象

有人反馈说,他把我的程序A和B安装在一个路径有空格的文件夹(C:\Program Files (x86))里,然后启动程序A,然后他发现程序A不能自动启动程序B。他下载了源代码,自己编译后调试,发现CreateProcess函数返回193错误(不是有效的Win32应用程序)。然后他才发现,是我忘记给路径加引号。他加了引号之后,问题就解决了。

异常

啊,我居然忘记加引号!这么明显的错误!等等,我好像……

对,没错,我也把程序A和B安装在C:\Program Files (x86)里面了啊!如果忘记加引号就会导致CreateProcess调用失败,那么两年来我的程序A到底是怎么把程序B启动的???!!!

微软的“关爱”

微软的CreateProcess函数手册是这么写的

lpApplicationName 参数可以为NULL。在这种情况下,lpCommandLine字符串中第一个由空格分隔的标记必须是模块名称。如果使用的长文件名包含空格,请使用带引号的字符串指示文件名的结尾和参数的开头;否则,文件名不明确

例如,考虑字符串c:\program files\sub dir\program name。该字符串可以通过多种方式解释。系统尝试按以下顺序解释这些可能性:
c:\program.exe
c:\program files\sub.exe
c:\program files\sub dir\program.exe
c:\program files\sub dir\program name.exe

震惊

所以答案是,在我的系统内,CreateProcess先后尝试了以下路径:
C:\Program.exe
C:\Program Files.exe
C:\Program Files (x86)\B.exe

经过3次尝试,终于找到了B.exe,真是辛苦它了啊!

但不得不说,微软为了掩盖程序猿的错误如此煞费苦心,真是惊掉了我的下巴,刷新了我的三观。


根据真实案例改编,情节有简化。

真实案例现场:

https://www.nexusmods.com/skyrimspecialedition/mods/16514?tab=bugs&BH=0

点击Failed to initialize speech recognition service展开内容。

image.png

回复列表(7|隐藏机器人聊天)
  • @Ta / 2020-10-29 / /

    我顶🔝
    米婊http://hacker.hk精品域名出售Dark's Bloghttps://ii.doYes , I do淘宝优惠券http://www.ii.do省钱实惠购物

  • @Ta / 2020-10-29 / /
    程序猿好难做
  • @Ta / 2020-10-29 / /

    这应该是为自己的win32、win64、以及UWP应用不同结构做的hack补丁吧
    小米MIX2s(白)

  • @Ta / 2020-10-29 / /
    这不叫掩盖错误,这叫高度兼容性
  • @Ta / 2020-10-29 / /
    被禁言
    用户被禁言,发言自动屏蔽。
  • mio
    @Ta / 2020-10-29 / /

    微软32位和64位系统的文件夹路径也是很让人迷惑了

  • @Ta / 2020-10-29 / /

    @net909,但微软至少在某个版本的操作系统内搞砸了这种兼容性,所以文中的“他”才遇到了如此棘手的问题。

    而如果微软从刚开始就没有这种让我震惊的“兼容性”,那么我根本就不会忘记加引号,因为我肯定早就发现程序B不能启动,然后修复问题了。

    而且从原则上来说,路径有空格并且忘记加引号,显然是一个错误。但是错误的输入却没有得到错误的结果,微软显然是掩盖了我的错误。而我不希望这种事情存在,因为这是为更大、更难追查的错误埋下了伏笔。

    完全崩溃比勉强能运行好多了。因为完全崩溃意味着明确的错误,修复起来也很简单。而勉强能运行的话,当在某人那里突然不能运行的时候,程序猿和用户都会很蛋疼。

添加新回复
回复需要登录