C ++使用命令行的Winapi CreateProcess问题

时间:2015-09-25 08:01:09

标签: c++ winapi parameters null createprocess

我以这种方式使用CreateProcess

resultCreate = CreateProcess(Command, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

//"Command" contains the executable file to execute
//"CommandLine" contains the parameters to pass to that executable

参数如下:

Param1: "C:\Users\myuser\Desktop\file.dll"
Param2: "file" (module name)
Param3: " " (blank)

因此完整的CommandLine字符串将是:

"C:\Users\myuser\Desktop\file.dll" file " "

CreateProcess成功运行可执行文件并应用前两个参数,但是当到达第三个参数时,它会抛出错误

The specified process could not be found.
Function " " could not be called, due to " " doesn't exist in the DLL "(null)"

如何正确传递所需参数?

1 个答案:

答案 0 :(得分:4)

当使用lpApplicationNamelpCommandLine时,您需要将可执行路径包含为lpCommandLine值的第一个参数,即使您在lpApplication中指定了可执行路径{1}}价值。 lpCommandLine按原样传递给生成的进程,并且大多数RTL(尤其是基于C的RTL,但也包括其他RTL)期望第一个命令行参数是可执行路径,因为这是命令行的方式游戏机操作。甚至在CreateProcess() documentation

中也提到了这一点
  

如果 lpApplicationName lpCommandLine 都是非NULL,则 lpApplicationName 指向的以null结尾的字符串指定要执行的模块,并且 lpCommandLine 指向的以null结尾的字符串指定命令行。新进程可以使用GetCommandLine来检索整个命令行。 用C编写的控制台进程可以使用argc和argv参数来解析命令行。因为argv [0]是模块名称,所以C程序员通常会重复模块名称作为命令行中的第一个标记。

这也包含在MSDN支持中:

INFO: Understanding CreateProcess and Command-line Arguments

  

创建32位进程时CreateProcess()的行为

     

案例1:

     

如果传递ApplicationName参数且CommandLine参数为NULL,则ApplicationName参数也用作CommandLine。这并不意味着您可以在ApplicationName字符串中传递其他命令行参数。例如,以下调用将失败并显示" File Not Found"错误:

CreateProcess( "c:\\MyApp.exe Param1 Param2", NULL, ... )
     

案例2:

     

另一方面,如果CommandLine参数为非NULL且ApplicationName参数为NULL,则API会尝试从CommandLine参数中提取应用程序名称。

     

案例3:

     

当您将有效的字符串指针传递给ApplicationName和CommandLine参数时,会出现CreateProcess()函数的灵活性(以及可能的混淆点)。这允许您指定要执行的应用程序以及传递给应用程序的完整命令行。可以假设传递给创建的应用程序的命令行是ApplicationName和CommandLine参数的组合,但事实并非如此。因此,CreateProcess创建的进程可以接收除.exe名称以外的值作为其" argv [0]"参数。以下是对CreateProcess的调用示例,该调用产生了这个"异常"行为:

CreateProcess( "c:\\MyApp.exe", "Param1 Param2 Param3", ...)
     

MyApp的论点如下:

argv[0] == "Param1"
argv[1] == "Param2"
argv[2] == "Param3"
     

注意:ANSI规范要求argv [0]应该等于应用程序名称,但CreateProcess为调用应用程序提供了为32位进程覆盖此规则的灵活性。

案例#3适用于您的情况。

使用类似的东西:

std::string Command = "<exe path>";
std::string CommandLine = "\"" + Command + "\" <parameters>";

// std::string::c_str() returns a const pointer. The first parameter
// of CreateProcessA() is const, but the second parameter must be a
// non-const pointer to writable memory, because CreateProcessW() can
// modify the data...
//
resultCreate = CreateProcessA(Command.c_str(), &CommandLine[0], ...);

std::wstring Command = L"<exe path>";
std::wstring CommandLine = L"\"" + Command + L"\" <parameters>";

// std::wstring::c_str() returns a const pointer. The first parameter
// of CreateProcessW() is const, but the second parameter must be a
// non-const pointer to writable memory, because CreateProcessW() can
// modify the data...
//
resultCreate = CreateProcessW(Command.c_str(), &CommandLine[0], ...);

或者,省略lpApplicationName并仅指定lpCommandLine的完整命令行:

std::string CommandLine = "\"<exe path>\" <parameters>";
resultCreate = CreateProcessA(NULL, &CommandLine[0], ...);

std::wstring CommandLine = L"\"<exe path>\" <parameters>";
resultCreate = CreateProcessW(NULL, &CommandLine[0], ...);