【问题标题】:Windows API - CreateProcess() path with spaceWindows API - 带空格的 CreateProcess() 路径
【发布时间】:2010-10-29 15:17:26
【问题描述】:

如何将带空格的路径传递给 CreateProcess() 函数?

以下作品

STARTUPINFO si;
            PROCESS_INFORMATION pi;

            ZeroMemory( &si, sizeof(si) );
            si.cb = sizeof(si);
            ZeroMemory( &pi, sizeof(pi) );

            if( !CreateProcess(_T("c:\\installer\\ew3d.exe"),    // No module name (use command line)
                _T("c:\\installer\\ew3d.exe /qr"),//argv[1],        // Command line
                NULL,           // Process handle not inheritable
                NULL,           // Thread handle not inheritable
                FALSE,          // Set handle inheritance to FALSE
                0,              // No creation flags
                NULL,           // Use parent's environment block
                NULL,           // Use parent's starting directory 
                &si,            // Pointer to STARTUPINFO structure
                &pi )           // Pointer to PROCESS_INFORMATION structure
                ) 
            {
                printf( "CreateProcess failed (%d).\n", GetLastError() );
                return false;
            }

            //Wait until child process exits.
            WaitForSingleObject( pi.hProcess, INFINITE );

            // Close process and thread handles. 
            CloseHandle( pi.hProcess );
            CloseHandle( pi.hThread );

但是如果我像下面的代码那样使用带空格的路径,它就不起作用了。

CreateProcess(_T("c:\\master installer\\ew3d.exe"),    // No module name (use command line)
                    _T("c:\\master installer\\ew3d.exe /qr"),//argv[1],        // Command line
                    NULL,           // Process handle not inheritable
                    NULL,           // Thread handle not inheritable
                    FALSE,          // Set handle inheritance to FALSE
                    0,              // No creation flags
                    NULL,           // Use parent's environment block
                    NULL,           // Use parent's starting directory 
                    &si,            // Pointer to STARTUPINFO structure
                    &pi )           // Pointer to PROCESS_INFORMATION structure
                    ) 

并且引用如下命令也无济于事

CreateProcess(_T("\"c:\\master installer\\ew3d.exe\""),    // No module name (use command line)
                    _T("\"c:\\master installer\\ew3d.exe\" /qr"),//argv[1],        // Command line
                    NULL,           // Process handle not inheritable
                    NULL,           // Thread handle not inheritable
                    FALSE,          // Set handle inheritance to FALSE
                    0,              // No creation flags
                    NULL,           // Use parent's environment block
                    NULL,           // Use parent's starting directory 
                    &si,            // Pointer to STARTUPINFO structure
                    &pi )           // Pointer to PROCESS_INFORMATION structure
                    ) 

什么是带空格的路径的正确通过方式?

【问题讨论】:

  • 刚刚在编辑中发布了对我来说可以的代码 - 不明白为什么它不适合你
  • 它在 Windows Vista 32 上,我使用的是 VS 2010。它在不同操作系统上的工作方式会有所不同吗?

标签: winapi


【解决方案1】:

针对另一个答案,示例#3 不是正确的答案。

问题是引号应该封装作为CreateProcess的第一个参数传递的模块路径名。但是,引号 应该 封装 arg0(同样是模块路径)作为传递给命令行(CreateProcess 的第二个参数)。

所以,正确的翻译应该是:

CreateProcess(_T("c:\\master installer\\ew3d.exe"),    
                    _T("\"c:\\master installer\\ew3d.exe\" /qr"),
                    NULL,           // Process handle not inheritable
                    NULL,           // Thread handle not inheritable
                    FALSE,          // Set handle inheritance to FALSE
                    0,              // No creation flags
                    NULL,           // Use parent's environment block
                    NULL,           // Use parent's starting directory 
                    &si,            // Pointer to STARTUPINFO structure
                    &pi )           // Pointer to PROCESS_INFORMATION structure
                    ) 

【讨论】:

    【解决方案2】:

    你的第三个 sn-p 是正确的,不知道你为什么会遇到麻烦。 GetLastError() 返回值在这里很有价值。但是请注意 CreateProcess 的第二个参数是 LPTSTR,不是 LPCTSTR。换句话说,Windows 可以写回字符串。非常令人毛骨悚然,不是吗?也许有足够的理由使用 ShellExecuteEx()。

    【讨论】:

    • 对于第三个 sn-p,GetLastError() 返回 123,表示“文件名、目录名或卷标语法不正确。”
    • 不寻常。您使用的路径是完全发布的还是您修改过的?
    • 从我的测试应用程序中完全复制。
    • 是的,我放弃了 CreateProcess() 并使用 ShellExcuteEx() 不再有这个问题了。但是我有一个很奇怪的问题也许你可以看看 - stackoverflow.com/questions/4058073/…
    • 问题是引号不应该封装模块路径名(CreateProcess的第一个参数)。这就是错误是路径不存在的原因。但是,您应该继续引用为命令行传递的封装 arg0(同样是模块路径)(CreateProcess 的第二个参数)。我在下面发布了新答案。
    【解决方案3】:

    您不需要在第一个和第二个参数中都指定应用程序路径。根据 MSDN documentation,如果您在第一个参数中列出应用程序名称,则第二个参数应该只是命令行参数。否则,将第一个参数设置为NULL,然后在第二个参数中将应用程序名称括在引号中(如果它包含空格)。不知道为什么您的最后一个列表不起作用。

    【讨论】:

    • 我从stackoverflow.com/questions/1135784/… 得到了这个想法(在两个参数上放置完整路径)。事实上我测试了它 - 如果我没有在两个参数中输入完整路径,它就会失败。
    【解决方案4】:

    文档不清楚,但如果您包含空格,您似乎必须允许参数 2 定义完整路径。

    lpApplicationName 参数可以是 空值。在这种情况下,模块名称 一定是第一个白 空格分隔的标记 lpCommandLine 字符串。如果您正在使用 包含一个长文件名 空格,使用带引号的字符串来表示 文件名结束的地方和 争论开始;否则,文件 名称不明确。

    你试过这种变体吗?

    CreateProcess(NULL,    // No module name (use command line)
                  _T("\"c:\\master installer\\ew3d.exe\" /qr"),//argv[1],        // Command line
                  NULL,           // Process handle not inheritable
                  NULL,           // Thread handle not inheritable
                  FALSE,          // Set handle inheritance to FALSE
                  0,              // No creation flags
                  NULL,           // Use parent's environment block
                  NULL,           // Use parent's starting directory 
                  &si,            // Pointer to STARTUPINFO structure
                  &pi )           // Pointer to PROCESS_INFORMATION structure
                 ) 
    

    编辑:以下对我有用(dwError 为 0)。我的项目是用多字节字符集构建的。

    LPTSTR szCmdLine = _tcsdup(TEXT(
        "\"C:\\Program Files\\adobe\\Reader 8.0\\reader\\acrord32.exe\" /qr"));
    CreateProcess(NULL,
                  szCmdLine,
                  NULL,           // Process handle not inheritable
                  NULL,           // Thread handle not inheritable
                  FALSE,          // Set handle inheritance to FALSE
                  0,              // No creation flags
                  NULL,           // Use parent's environment block
                  NULL,           // Use parent's starting directory 
                  &si,            // Pointer to STARTUPINFO structure
                  &pi            // Pointer to PROCESS_INFORMATION structure
                 );     // This works. Downcasting of pointer to members in general is fine.
    
    DWORD error = GetLastError();
    

    【讨论】:

      【解决方案5】:

      聚会有点晚了。出于某种原因,我不能对 Praetorian 投赞成票,但他是对的。我遇到了同样的问题,将应用程序名称归零就可以了。我还尝试了应用名称中的路径和第二个参数中的命令行参数,但无济于事。

      我在 Win7 x64 上。

      CreateProcess(NULL, "\"exe的路径\" -x -y -z", ...);

      为我工作。

      【讨论】:

      • 这行得通,但不是 100% 迂腐正确。我的回答(最受好评的回答)解释了完整的背景。上面接受的答案是错误的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 2015-06-18
      • 2014-09-07
      • 1970-01-01
      相关资源
      最近更新 更多