CreateProcess doesn't pass command line argume

2019-01-09 14:57发布

问题:

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

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:

// 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.

Object reference not set to an instance of an object

回答1:

You should specify also the module name in parameters: LPTSTR cmdArgs = "App name@example.com"; It should be the whole command line (including argv[0]).



回答2:

If the first parameter to CreateProcess() is non-NULL, it will use that to locate the image to launch.

If it is NULL, it will parser the 2nd argument to try to get the executable to launch from the 1st token.

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].

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):

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!


回答3:

It doesn't look like you are using CreateProcess correctly, see 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.

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.

// NOTE THE Null-Terminated string too!
LPTSTR cmdArgs = "D:\\email\\smtp.exe name@example.com\0";


回答4:

Below is a cut down version of the code used by the Zeus IDE to run external processes:

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 = "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.



回答5:

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


回答6:

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.



回答7:

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.

Therefore you can try using LPTSTR cmdArgs = _tcsdup("name@example.com").

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.



回答8:

You can add a space as first character of the cmdArgs string:

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. So adding a space will properly separate the arguments.