CreateProcess and command line arguments

17,385

Solution 1

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 "/C C:\\Temp\\sift.exe < C:\\img1.pgm > C:\\img1.key". The actual path to cmd.exe can be determined by reading the %COMSPEC% environment variable.

Solution 2

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.

Share:
17,385
user850275
Author by

user850275

Updated on June 04, 2022

Comments

  • user850275
    user850275 about 2 years

    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.

    • Aleks G
      Aleks G over 12 years
      Just a thought: what if you run command cmd.exe with parameters /c c:\temp\sift.exe < c:\img1.pmg > c:\img1.key?
  • Eugene
    Eugene over 12 years
    I've not meant that CreateProcess is a command line processor. I've meant that it can't accept redirections as arguments of a process. And if one wats to use the redirections it should explicitely provide the corresponding code.
  • Sam
    Sam over 12 years
    I agree, I was pointing out why it can't accept redirections as arguments...because that is something the Windows command line processor does.
  • user850275
    user850275 over 12 years
    Ahhh, I see. That would make more sense. This is my first time getting serious with programming in Windows. Thanks for the insight
  • Remy Lebeau
    Remy Lebeau almost 7 years
    "Nowadays, if you wanted to use it with CMD.exe, you would need to provide the full path in the first parameter and in the second parameter, include the application from the first parameter" - using the first parameter is not a requirement. You can alternatively set the first parameter to NULL, then CreateProcess() will parse out the EXE to run from the second parameter. This is the easier and more common scenario, and is fully documented. CreateProcess(NULL, "C:\\Windows\\System32\\cmd.exe <params>", ...);
  • Remy Lebeau
    Remy Lebeau almost 7 years
    Your (char*) typecast is redundant when compiling for ANSI/MBCS, and is a hidden runtime bug when compiling for Unicode. Best to just get rid of it completely. In the latter case, you can't pass a literal to the parameter anyway (runtime crash), so you should copy the path to a local char[]/wchar_t[] array first and then pass that instead.
  • kayleeFrye_onDeck
    kayleeFrye_onDeck almost 7 years
    Wow! What a nasty little pitfall :( Updated now! ^_^ Tyvm, @RemyLebeau!