WinAPI - 当C:\ Program文件存在时,CreateProcessW失败

vig*_*esh -3 c winapi createprocess

我运行以下C代码来创建一个进程.exe文件位于C:\ Program Files\Exes\Start\process1.exe

CreateProcessW(NULL, (char*) exePath, 
                           NULL, NULL, TRUE, 
                           flags, 
                           NULL, NULL, &startupInfo, &processInformation);
Run Code Online (Sandbox Code Playgroud)

现在有些计算机随机拥有名为Program的文件位于C:\ Program,导致create process失败并显示错误:

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

有没有办法解决这个问题,除了重命名文件,因为有几十个Windows Vms执行此C代码.这个错误随机发生在几台机器上.

Chr*_*cke 5

这段代码甚至可以编译?CreateProcessW的第二个参数定义为a LPWSTR,这意味着它只应接受一个宽字符串.

下一个问题:作为演员的结果,无法确定其来源exePath.这是因为第二个参数被定义为a LPWSTR,而不是LPCWSTR(即一个const宽字符串),原因是:CreateProcessW可以写入缓冲区.

然后是第3个问题 - 你的exe路径中有一个空格.当作为第二个参数(lpCommandLine)传递时,CreateProcess有一些derpy逻辑来猜测exe名称的结束位置和命令行的开始位置.这需要编码命令行的exe路径部分的引号.

当你拥有exe的完整路径 - 而且没有参数时 - 最简单/最安全的做法就是将它作为lpApplicationName参数传递给它.这是一个const参数,它可以避免在命令行源是常量字符串文字等时可能导致的任何潜在的未定义行为.它只是用作执行exe的路径,因此不会(也不能)有任何引用要求.

    CreateProcess(exePath,NULL,...);
Run Code Online (Sandbox Code Playgroud)

除此之外:使用这两个参数CreateProcess基本上可以让您将启动的应用程序的argv [0]设置为您想要的任何内容.所以你可以从特定的路径/ exe名称运行一个应用程序,但是让argv [0]指向其他路径或exe名称.

要将参数传递给exe,而不是传递完整的(引用封闭的)路径,您可以执行以下简单操作:

    WCHAR cmdLine[] = TEXT("console1.exe --version");
    CreateProcessW(exePath,cmdLine,...);
Run Code Online (Sandbox Code Playgroud)

Edits Credit对Paul Sanders和其他评论指出了不引用的exe路径,并且还让我完全打破了原来的答案,这个答案在没有我意识到的情况下解决了这个问题.感谢RbMm的发现我已经打破了我的答案,并且向eryksun表示我已经阅读了20年以来错误的文档了.

  • 不要挑剔,但重要的是澄清一个Windows进程本身并不具有`argv`,这是一个与`exec*`函数系列相关的Unix概念.为了兼容性,Windows CRT的`[w] main`入口点具有`argv`,但加载程序调用的实际入口点传递指向进程环境块(PEB)的指针.这包括`ProcessParameters`,包括`ImagePathName`和`CommandLine`,当然这是多余的,因为应用程序可以调用`GetModuleFileNameW(NULL,...)`和`GetCommandLineW()`. (2认同)
  • @ChrisBecke,如果`lpCommandLine`为'NULL`,则引用`lpApplicationName`作为命令行.如果`lpApplicationName`为'NULL`,则通过解析`lpCommandLine`并调用`SearchPathW`来确定基本API的自定义搜索路径中的可执行文件来确定图像路径. (2认同)