您好我有以下代码,但它没有按预期工作,无法弄清楚问题是什么。
基本上,我正在执行一个进程(一个.NET进程)并传递它的命令行参数,它由CreateProcess()成功执行但CreateProcess()没有传递命令行参数
我在这里做错了什么?
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 = "name@example.com";
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;
}
编辑:如果我像这样传递cmdArgs
,还有一件事:
// a space as the first character
LPTSTR cmdArgs = " name@example.com";
然后我收到错误,然后CreateProcess返回TRUE
但我的目标进程没有执行。
Object reference not set to an instance of an object
答案 0 :(得分:23)
您应在参数中指定还模块名称:LPTSTR cmdArgs = "App name@example.com";
它应该是整个命令行(包括argv [0])。
答案 1 :(得分:17)
如果CreateProcess()
的第一个参数是非NULL,它将使用它来定位要启动的图像。
如果为NULL,它将解析第二个参数以尝试从第一个令牌启动可执行文件。
在任何一种情况下,C运行时都将使用第二个参数来填充argv
数组。因此,该参数中的第一个标记显示在argv[0]
。
您可能需要以下内容(我已将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 name@example.com";
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;
}
这是我从该程序获得的输出:
echoargs.exe name@example.com
[0]: echoargs.exe
[1]: name@example.com
Yohoo!
答案 2 :(得分:5)
看起来您没有正确使用CreateProcess,请参阅http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx。
要执行的命令行。此字符串的最大长度为32,768个字符,包括Unicode终止空字符。如果lpApplicationName为NULL,则lpCommandLine的模块名称部分限制为MAX_PATH个字符。
lpCommandLine参数可以为NULL。在这种情况下,该函数使用lpApplicationName指向的字符串作为命令行。
如果lpApplicationName和lpCommandLine都是非NULL,则lpApplicationName指向的以null结尾的字符串指定要执行的模块,lpCommandLine指向的以null结尾的字符串指定命令行。新进程可以使用GetCommandLine来检索整个命令行。用C编写的控制台进程可以使用argc和argv参数来解析命令行。因为argv [0]是模块名称,所以C程序员通常会重复模块名称作为命令行中的第一个标记。
因此,在您的情况下,您需要将此作为命令参数,并且应该为第一个参数传递NULL以获得您想要的行为。
// NOTE THE Null-Terminated string too!
LPTSTR cmdArgs = "D:\\email\\smtp.exe name@example.com\0";
答案 3 :(得分:5)
以下是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);
}
pszCommand 将是完整的可执行路径和文件名和参数,例如:
pszCommand = "D:\\email\\smtp.exe name@example.com";
据我所知,两者之间唯一真正的区别是,在 Zeus 示例中, dwCreationFlags 参数设置为 CREATE_NEW_PROCESS_GROUP 强>价值。
答案 4 :(得分:2)
试试这个:
LPTSTR cmdArgs = "name@example.com";
CString szcmdline("D:\\email\\smtp.exe");
szcmdline += _T(" ") + cmdArgs ;
//Leave first param empty and pass path + argms in
if(CreateProcess(NULL, szcmdline, second
答案 5 :(得分:1)
您可以添加空格作为cmdArgs字符串的第一个字符:
LPTSTR cmdArgs = " name@example.com";
显然,Windows将第二个参数字符串附加到第一个参数表示的应用程序名称,结果作为命令行参数传递给可执行文件。因此,添加空格将正确地分隔参数。
答案 6 :(得分:0)
此函数的Unicode版本CreateProcessW可以修改此字符串的内容。因此,此参数不能是只读内存的指针(例如const变量或文字字符串)。如果此参数是常量字符串,则该函数可能会导致访问冲突。
因此,您可以尝试使用LPTSTR cmdArgs = _tcsdup("name@example.com")
。
另一个问题是:目标进程如何读取参数?使用argv [0]作为应用程序名称?然后你应该将应用程序名称附加为第一个参数。
答案 7 :(得分:0)
您没有为字符串分配内存。
而不是:
LPTSTR cmdArgs = "name@example.com";
尝试:
TCHAR cmdArgs[] = "name@example.com";
编辑: 然后致电:
CreateProcess("D:\\email\\smtp.exe", &cmdArgs[0], ...
这将在堆栈上创建一个本地数组,然后将指针传递给该数组。