简体   繁体   中英

CreateProcess and command line arguments

Background Info: Windows 7, Visual C++ 2010 Express

Problem: CreateProcess() keeps returning with 'Invalid command line argument'

Explanation: I'm writing a piece of code that calls external programs using the Windows API's CreateProcess. I've gotten the call to work with one external program so far:

if( !CreateProcess( "C:\\Temp\\convert.exe",
    t_str,        // Arguments
    ...
}
//where t_str is " C:\\img1.jpeg C:\\img1.pgm" (ImageMagick if you're wondering). 

This works perfectly even with the amount of data-mangling I did to push everything into the Windows strings and pointers. So I copied all of the mangling for CreateProcess() for another call to a different external program:

 if( !CreateProcess( "C:\\Temp\\sift.exe",
     t_str2,        // Arguments
     ...
 }
 //where t_str2 is ` < C:\\img1.pgm > C:\\img1.key`

Basically, something very similar, but with all the variable names changed (since I have these two calls running serial). And this is where the problem is; this doesn't run, and, instead, prints out "Invalid command line argument: < C:\\img1.pgm". Of course, this command works fine in the command prompt, but not in my code.

I switched t_str2 to something else a little less complicated(since I know how sift.exe works) and I get the same result. Same thing happens when I run just sift and not convert.

Question: What could be causing this problem? What could I do to further debug this problem? Any suggestions on alternatives to the methods I'm using? Any help is appreciated. I can provide further code, but It's pretty straight forward, and not much could go wrong with it.

You cannot use command-line redirection operators with CreateProcess() directly. You have to spawn an instance of cmd.exe and pass the operators to it instead, eg:

CreateProcess( "C:\\windows\\system32\\cmd.exe", t_str2, ...))

Where t_str2 is "/CC:\\\\Temp\\\\sift.exe < C:\\\\img1.pgm > C:\\\\img1.key" . The actual path to cmd.exe can be determined by reading the %COMSPEC% environment variable.

In the second example you are trying to use standard input and out redirections, which are notations of the command line application. But they are not valid program arguments. If you want use redirection you should open pipes and manualy read and write from/to input/output files. Here you can find an example how to implement pthe process creation with input/output redirections.

CreateProcess has some annoying gotchas, and the older answers across Stack Exchange can make that process somewhat troublesome if you're not also referencing the official documentation.

  1. Parameter 1 for CreateProcess is for the most part optional, which is really weird for a first parameter. If you don't want to specify it, use NULL , otherwise you should read the very specific documentation on how to use parameter 1 when not setting it to NULL .
  2. If setting parameter 1 to NULL , the application needs to be the first part of parameter 2.

Thanks again to Remy for clearing up the weird behavior on my initial answer.


This code sample only requires a basic VC++ compiler on Windows and the ability to make and store a file on the Desktop that will be opened by Notepad.

If that's not practical, feel free to use %temp% or some other location for placing the test file. The app will run until you close notepad.exe. This also handles getting and returning the exit code. If you don't want it to run indefinitely until exit, you'll need to update the WaitForSingleObject line.

#include <Windows.h>

int main()
{
    STARTUPINFOA startup_info = { 0 };
    LPSTARTUPINFOA p_startup_info = &startup_info;
    PROCESS_INFORMATION proc_info = { 0 };
    LPPROCESS_INFORMATION p_proc_info = &proc_info;
    char command_line[] = 
      "C:\\Windows\\System32\\cmd.exe /C notepad.exe \"%USERPROFILE%\\Desktop\\test.txt\"";

    bool process_created = CreateProcess(
        NULL,
        command_line,
        NULL,
        NULL,
        FALSE,
        DETACHED_PROCESS,
        NULL,
        NULL,
        p_startup_info,
        p_proc_info
    );

    if (!process_created) { return -3; }

    DWORD process_exit;

    WaitForSingleObject(proc_info.hThread, INFINITE);

    GetExitCodeProcess(p_proc_info->hProcess, &process_exit);

    return (int)process_exit;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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