简体   繁体   English

CreateProcess不传递命令行参数

[英]CreateProcess doesn't pass command line arguments

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 = "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;
}

EDIT: Hey one more thing, if I pass my cmdArgs like this: 编辑:嘿,还有一件事,如果我像这样传递我的cmdArgs

// a space as the first character
LPTSTR cmdArgs = " name@example.com";

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

You should specify also the module name in parameters: LPTSTR cmdArgs = "App name@example.com"; 你应该在参数指定模块名称: LPTSTR cmdArgs = "App name@example.com"; It should be the whole command line (including argv[0]). 它应该是整个命令行(包括argv [0])。

If the first parameter to CreateProcess() is non-NULL, it will use that to locate the image to launch. 如果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. 在任何一种情况下,C运行时都将使用第二个参数来填充argv数组。 So the first token from that parameter shows up in argv[0] . 因此该参数的第一个标记显示在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 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;
}

Here's the output I get from that program: 这是我从该程序得到的输出:

echoargs.exe name@example.com
[0]: echoargs.exe
[1]: name@example.com

Yohoo!

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. 此字符串的最大长度为32,768个字符,包括Unicode终止空字符。 If lpApplicationName is NULL, the module name portion of lpCommandLine is limited to MAX_PATH characters. 如果lpApplicationName为NULL,则lpCommandLine的模块名称部分限制为MAX_PATH字符。

  • The lpCommandLine parameter can be NULL. lpCommandLine参数可以为NULL。 In that case, the function uses the string pointed to by lpApplicationName as the command line. 在这种情况下,该函数使用lpApplicationName指向的字符串作为命令行。

  • 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 . 如果lpApplicationName和lpCommandLine都是非NULL,则lpApplicationName指向的以null结尾的字符串指定要执行的模块,lpCommandLine指向的以null结尾的字符串指定命令行 The new process can use GetCommandLine to retrieve the entire command line. 新进程可以使用GetCommandLine来检索整个命令行。 Console processes written in C can use the argc and argv arguments to parse the command line. 用C编写的控制台进程可以使用argc和argv参数来解析命令行。 Because argv[0] is the module name, C programmers generally repeat the module name as the first token in the command line. 因为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 name@example.com\0";

Below is a cut down version of the code used by the Zeus IDE to 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 pszCommand would be the full executable path and file name and arguments so for example: pszCommand将是完整的可执行路径和文件名和参数,例如:

pszCommand = "D:\\email\\smtp.exe name@example.com";

From what I can tell, the only real difference between the two is that in the Zeus example, the dwCreationFlags argument is set to the CREATE_NEW_PROCESS_GROUP value. 据我所知,两者之间唯一真正的区别是,在Zeus示例中, dwCreationFlags参数设置为CREATE_NEW_PROCESS_GROUP值。

Try this: 尝试这个:

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

You can add a space as first character of the cmdArgs string: 您可以添加空格作为cmdArgs字符串的第一个字符:

LPTSTR cmdArgs = " name@example.com";

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. 显然,Windows将第二个参数字符串附加到第一个参数表示的应用程序名称,结果作为命令行参数传递给可执行文件。 So adding a space will properly separate the arguments. 因此,添加空格将正确地分隔参数。

The Unicode version of this function, CreateProcessW, can modify the contents of this string. 此函数的Unicode版本CreateProcessW可以修改此字符串的内容。 Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). 因此,此参数不能是只读内存的指针(例如const变量或文字字符串)。 If this parameter is a constant string, the function may cause an access violation. 如果此参数是常量字符串,则该函数可能会导致访问冲突。

Therefore you can try using LPTSTR cmdArgs = _tcsdup("name@example.com") . 因此,您可以尝试使用LPTSTR cmdArgs = _tcsdup("name@example.com")

Another problem is: how does the target process reads the arguments? 另一个问题是:目标进程如何读取参数? using argv[0] as application name? 使用argv [0]作为应用程序名称? Then you shoud append the application name as the first parameter too. 然后你应该将应用程序名称附加为第一个参数。

You are not allocating memory for your string. 您没有为字符串分配内存。

Instead of: 代替:

LPTSTR cmdArgs = "name@example.com";

try: 尝试:

TCHAR cmdArgs[] = "name@example.com";

Edit: then call: 编辑:然后致电:

 CreateProcess("D:\\email\\smtp.exe", &cmdArgs[0], ...

This will create a local array on the stack and then pass a pointer to that array. 这将在堆栈上创建一个本地数组,然后将指针传递给该数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM