传递给 CreateProcess 的参数没有像我预期的那样被解析

Posted

技术标签:

【中文标题】传递给 CreateProcess 的参数没有像我预期的那样被解析【英文标题】:Arguments being passed to CreateProcess aren't being parsed as I expected 【发布时间】:2012-03-13 19:14:06 【问题描述】:

我正在尝试使用 devcon.exe 检查各种硬件的状态。在示例中,我试图检查我的 SATA HBA 状态,但 devcon 对此抱怨不已。代码如下:

int main(int argc, char** argv) 
    std::string cmdLine("\"C:\\Users\\afalanga\\Documents\\Visual Studio 2010\\Projects\\PlayGround\\Debug\\devcon.exe\" status PCI\\VEN_8086^&DEV_3A22^&SUBSYS_75201462^&REV_00");

    char* pCmdLine(new char[cmdLine.length() + 10]);
    memset(pCmdLine, 0, cmdLine.length() + 10);

    for(int i(0); i < cmdLine.length(); i++)
        pCmdLine[i] = cmdLine.at(i);

    STARTUPINFO si =  sizeof(STARTUPINFO) ;
    PROCESS_INFORMATION pi = 0;

    if(!CreateProcess(NULL, pCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) 
        std::cout << "Create child process failed.  Error code: "
                  << GetLastError() << std::endl;
        return 1;
    

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);

    return 0;

问题是,当上述执行时,devcon 抱怨说,“没有找到匹配的设备”。但是,如果我将该命令行从调试器复制/粘贴到我的命令提示符中并按回车键(或者当然删除调试器放在它周围的所有包含引号),该命令将按预期完美执行。

我在处理字符串时出了什么问题?以上是阅读 MSDN 上的 CreateProcess() 文档的结果(发现不一定需要第一个参数,并且 cmd args 根本不应该去那里)。我分配 10 个额外字节的内存来将字符串复制到其中的原因是,“无论”可能在 CreateProcess() 函数的内部发生什么变化,都可以在不占用其他内存的情况下这样做。至少,当我这样做时,我是这么想的。

【问题讨论】:

不相关,但您正在泄漏内存,为什么有人会使用memset 而不是简单的() 【参考方案1】:

Command line metacharacters are parsed by the command processor。特别是您使用^ 来防止 CMD.EXE 破坏与符号处的命令。但是您正在直接执行程序,绕过 CMD.EXE。因此,^ 传递给 devcon.exe,后者被他们迷惑了。

解决方案:删除^ 字符。

您的问题实际上与您的标题相反。您传递给CreateProcess 的命令行被直接传递给应用程序完全按照您指定的方式

【讨论】:

谢谢!这就对了。我应该如何修改标题以便更好地参考?【参考方案2】:
std::string cmdLine("\"C:\\Users\\afalanga\\Documents\\Visual Studio 2010\\Projects\\PlayGround\\Debug\\devcon.exe\" status PCI\\VEN_8086^&DEV_3A22^&SUBSYS_75201462^&REV_00

推测^ 中的插入符号是在命令行解释器中输入的命令的残留物,它们用于关闭&amp; 的特殊含义。

只需删除插入符号。

还请注意,您当前的代码会泄漏内存。

为了避免这种情况,例如

string commandLineArg = cmdLine + '\0';

... CreateProcess( 0, &commandLineArg[0], ... )

【讨论】:

我觉得自己很愚蠢。我错过了删除 [] 缓冲区的失败。这是一个简单的程序,我用它来调试一大段代码中的问题。我实际上是在删除那里的记忆。但是,我认为这种方法要优雅得多。谢谢你的建议。【参考方案3】:

你可以这样试试吗:

CreateProcess(NULL, pCmdLine.c_str(), ...);

【讨论】:

【参考方案4】:

我用过:

TCHAR var[] = _T(" C:\\filepathe\\foo");

CreateProcess(NULL, var,...);

【讨论】:

以上是关于传递给 CreateProcess 的参数没有像我预期的那样被解析的主要内容,如果未能解决你的问题,请参考以下文章

将输入传递给由 CreateProcess() 创建的进程

将 STARTF_USESTDHANDLES 标志与 CreateProcess() 一起使用时将套接字传递给子进程时出错

将 0 传递给具有默认值的函数

cmd.exe 在使用 CreateProcess 调用后立即关闭

c ++ createprocess - 命令行参数的字符串var - 没有发生任何事情

CreateProcess 调用 cmd.exe 包括。没有显示(闪烁)窗口的参数?