C++ CreateProcess 不传递命令行参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1135784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CreateProcess doesn't pass command line arguments
提问by akif
Hello I have the following code but it isn't working as expected, can't figure out what the problem is.
您好,我有以下代码,但没有按预期工作,无法弄清楚问题是什么。
Basically, I'm executing a process (a .NET process) and passing it command line arguments, it is executed successfully by CreateProcess() but CreateProcess() isn't passing the command line arguments
基本上,我正在执行一个进程(一个 .NET 进程)并传递命令行参数,它由 CreateProcess() 成功执行,但 CreateProcess() 没有传递命令行参数
What am I doing wrong here??
我在这里做错了什么??
int main(int argc, char* argv[])
{
PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field
LPTSTR cmdArgs = "[email protected]";
if(CreateProcess("D:\email\smtp.exe", cmdArgs,
NULL,NULL,FALSE,0,NULL,
NULL,&StartupInfo,&ProcessInfo))
{
WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
printf("Yohoo!");
}
else
{
printf("The process could not be started...");
}
return 0;
}
EDIT:Hey one more thing, if I pass my cmdArgs
like this:
编辑:嘿还有一件事,如果我cmdArgs
像这样通过我的:
// a space as the first character
LPTSTR cmdArgs = " [email protected]";
Then I get the error, then CreateProcess returns TRUE
but my target process isn't executed.
然后我收到错误,然后 CreateProcess 返回TRUE
但我的目标进程没有执行。
Object reference not set to an instance of an object
回答by EFraim
You should specify alsothe module name in parameters: LPTSTR cmdArgs = "App [email protected]";
It should be the whole command line (including argv[0]).
您还应该在参数中指定模块名称:LPTSTR cmdArgs = "App [email protected]";
它应该是整个命令行(包括 argv[0])。
回答by Michael Burr
If the first parameter to CreateProcess()
is non-NULL, it will use that to locate the image to launch.
如果 to 的第一个参数CreateProcess()
非 NULL,它将使用它来定位要启动的图像。
If it is NULL, it will parser the 2nd argument to try to get the executable to launch from the 1st token.
如果它为 NULL,它将解析第二个参数以尝试从第一个令牌启动可执行文件。
In either case, the C runtime will use the second argument to populate the argv
array. So the first token from that parameter shows up in argv[0]
.
无论哪种情况,C 运行时都将使用第二个参数来填充argv
数组。所以来自该参数的第一个标记出现在argv[0]
.
You probably want something like the following (I've change the smtp.exe program to echoargs.exe - a simple utility I have to help figure out just this kind of issue):
您可能需要类似以下内容(我已将 smtp.exe 程序更改为 echoargs.exe - 我必须帮助解决此类问题的一个简单实用程序):
int main(int argc, char* argv[])
{
PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter
char cmdArgs[] = "echoargs.exe [email protected]";
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field
if(CreateProcess("C:\util\echoargs.exe", cmdArgs,
NULL,NULL,FALSE,0,NULL,
NULL,&StartupInfo,&ProcessInfo))
{
WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
printf("Yohoo!");
}
else
{
printf("The process could not be started...");
}
return 0;
}
Here's the output I get from that program:
这是我从该程序获得的输出:
echoargs.exe [email protected]
[0]: echoargs.exe
[1]: [email protected]
Yohoo!
回答by jussij
Below is a cut down version of the code used by the Zeus IDEto run external processes:
以下是Zeus IDE用于运行外部进程的代码的简化版本:
bool createProcess(const char *pszTitle, const char *pszCommand)
{
STARTUPINFO StartInfo;
memset(&StartInfo, 0, sizeof(StartInfo));
StartInfo.cb = sizeof(StartInfo);
StartInfo.lpTitle = (pszTitle) ? (char *)pszTitle : (char *)pszCommand;
StartInfo.wShowWindow = SW_NORMAL;
StartInfo.dwFlags |= STARTF_USESHOWWINDOW;
if (CreateProcess(0, (char *)pszCommand,
0, 0, TRUE,
CREATE_NEW_PROCESS_GROUP, 0, 0,
&StartInfo, &ProcessInfo))
{
lErrorCode = 0;
}
else
{
lErrorCode = GetLastError();
}
return (lErrorCode == 0);
}
The pszCommandwould be the full executable path and file name and arguments so for example:
该pszCommand将是完整的可执行文件的路径和文件名和参数,以便例如:
pszCommand = "D:\email\smtp.exe [email protected]";
From what I can tell, the only real difference between the two is that in the Zeusexample, the dwCreationFlagsargument is set to the CREATE_NEW_PROCESS_GROUPvalue.
据我所知,两者之间唯一真正的区别是在Zeus示例中,dwCreationFlags参数设置为CREATE_NEW_PROCESS_GROUP值。
回答by Ray Hayes
It doesn't look like you are using CreateProcess correctly, see http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx.
您似乎没有正确使用 CreateProcess,请参阅http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx。
The command line to be executed. The maximum length of this string is 32,768 characters, including the Unicode terminating null character. If lpApplicationName is NULL, the module name portion of lpCommandLine is limited to MAX_PATH characters.
The lpCommandLine parameter can be NULL. In that case, the function uses the string pointed to by lpApplicationName as the command line.
If both lpApplicationName and lpCommandLine are non-NULL, the null-terminated string pointed to by lpApplicationName specifies the module to execute, and the null-terminated string pointed to by lpCommandLine specifies the command line. The new process can use GetCommandLine to retrieve the entire command line. Console processes written in C can use the argc and argv arguments to parse the command line. Because argv[0] is the module name, C programmers generally repeat the module name as the first token in the command line.
要执行的命令行。此字符串的最大长度为 32,768 个字符,包括 Unicode 终止空字符。如果 lpApplicationName 为 NULL,则 lpCommandLine 的模块名称部分限制为 MAX_PATH 个字符。
lpCommandLine 参数可以为 NULL。在这种情况下,该函数使用 lpApplicationName 指向的字符串作为命令行。
如果 lpApplicationName 和 lpCommandLine 都非 NULL,则 lpApplicationName 指向的空终止字符串指定要执行的模块,lpCommandLine 指向的空终止字符串指定命令行。新进程可以使用 GetCommandLine 来检索整个命令行。用 C 编写的控制台进程可以使用 argc 和 argv 参数来解析命令行。因为 argv[0] 是模块名称,C 程序员通常在命令行中重复模块名称作为第一个标记。
So in your case, you need this as the command argument and should probably pass a NULL for the first parameter to get the behaviour your want.
因此,在您的情况下,您需要将其作为命令参数,并且可能应该为第一个参数传递一个 NULL 以获得您想要的行为。
// NOTE THE Null-Terminated string too!
LPTSTR cmdArgs = "D:\email\smtp.exe [email protected]LPTSTR cmdArgs = "[email protected]";
CString szcmdline("D:\email\smtp.exe");
szcmdline += _T(" ") + cmdArgs ;
//Leave first param empty and pass path + argms in
if(CreateProcess(NULL, szcmdline, second
";
回答by aJ.
回答by kundrata
You can add a space as first character of the cmdArgs string:
您可以添加一个空格作为 cmdArgs 字符串的第一个字符:
LPTSTR cmdArgs = " [email protected]";
LPTSTR cmdArgs = " [email protected]";
Apparently Windows appends the 2nd argument string to the application name represented by the first argument, and the result is passed as command line arguments to the executable. So adding a space will properly separate the arguments.
显然,Windows 将第二个参数字符串附加到第一个参数表示的应用程序名称,并将结果作为命令行参数传递给可执行文件。因此,添加一个空格将正确分隔参数。
回答by Vlagged
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
此函数的 Unicode 版本 CreateProcessW 可以修改此字符串的内容。因此,此参数不能是指向只读内存的指针(例如 const 变量或文字字符串)。如果此参数是一个常量字符串,该函数可能会导致访问冲突。
Therefore you can try using LPTSTR cmdArgs = _tcsdup("[email protected]")
.
因此,您可以尝试使用LPTSTR cmdArgs = _tcsdup("[email protected]")
.
Another problem is: how does the target process reads the arguments? using argv[0] as application name? Then you shoud append the application name as the first parameter too.
另一个问题是:目标进程如何读取参数?使用 argv[0] 作为应用程序名称?然后你也应该附加应用程序名称作为第一个参数。
回答by morechilli
You are not allocating memory for your string.
您没有为字符串分配内存。
Instead of:
代替:
TCHAR cmdArgs[] = "[email protected]";
try:
尝试:
CreateProcess("D:\email\smtp.exe", &cmdArgs[0], ...
Edit: then call:
编辑:然后调用:
##代码##This will create a local array on the stack and then pass a pointer to that array.
这将在堆栈上创建一个本地数组,然后传递一个指向该数组的指针。