3

This is related to: How do I read the results of a system() call in C++?

I am trying to do the exact the same thing only that my program needs to pass 'multiple parameters with spaces' to the command. I need the command line output and the exit code from the process.

Example: An example with Textpad. The application I'm really using prints stuff on stdout.


string command1 = "\"C:\Program Files\TextPad 5\Textpad.exe\" C:\readme0.txt";
string command2 = "\"C:\Program Files\TextPad 5\Textpad.exe\" \"C:\read me2.txt\"";
cout << system(command1.c_str()) << endl;
cout << system(command1.c_str()) << endl;

Output:

0 'C:\Program' is not recognized as an internal or external command, operable program or batch file.

1

The first call to system passes and second one fails with the error above. _popen in Windows works similarly on Windows so no help there. I can easily do this on Linux as I can escape spaces in the parameters without having to use quotes.

An alternative is to write a huge chunk of non-cross-platform code as listed here: http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx

But in case I want to avoid that, are there any alternatives to system() and _popen() on Windows?

Thanks!

Community
  • 1
  • 1
Sameer
  • 231
  • 3
  • 11
  • Did you intend for the backslash in your example code to be single? Inside the C string you need to use "\\" to get C to escape to a single backslash, but possibly you knew that and the StackOverflow formatting code has just messed up your example... – DavidK Feb 12 '09 at 13:28
  • Yeah, my double backslashes have been replaced with single backslashes. – Sameer Feb 13 '09 at 05:58

6 Answers6

2

The lowest level Windows API function used by _popen() and system() is CreateProcess().

However CreateProcess() is not that simple to use - especially when you want to get the process'es output or write to the process'es input.

CreateProcess() will definitely work with file names that contain space characters (as long as they are written in quotation marks the way you did that).

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
0

I do this (note - this is VB.NET code), so I can write the output of the command to my log file (it's wrapped in a RunCommand() method):

 Try
    Dim myprocess As New Process()
    myprocess.StartInfo.FileName = "C:\Program Files\TextPad 5\Textpad.exe"
    myprocess.StartInfo.RedirectStandardOutput = True
    myprocess.StartInfo.UseShellExecute = False

    ' inArgs are the arguments on the command line to the program
    myprocess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
    myprocess.StartInfo.Arguments = "C:\readme0.txt"

    ' the dir to set as default when the program runs
    Then myprocess.StartInfo.WorkingDirectory = "C:\Program Files\TextPad 5\"

    myprocess.Start()

    ' grab a reader to the standard output of the program
    procReader = myprocess.StandardOutput()

    ' read all the output from the process
    While (Not procReader.EndOfStream)
       procLine = procReader.ReadLine()

       ' write the output to my log
       writeNotes(procLine)
    End While

    procReader.Close()

 Catch ex As Exception
    ' Write the error to my log
    writeErrors("Couldn't execute command "C:\Program Files\TextPad 5\Textpad.exe", ex)
 End Try
Ron Savage
  • 10,923
  • 4
  • 26
  • 35
0

The following solves the spaces in the path problem. Catching the output of the command is much more difficult, however:

#include <string>
#include <cstdlib>
using namespace std;

int main() {
    string cmd = "\"c:\\program files\\notepad++\\notepad++.exe\"";
    system( cmd.c_str() );
    return 0;
}
0

A bunch of utility libraries have taken that chunk of non-portable code and wrapped it up with a portable interface. For an example, see Qt's QProcess.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
-1

I think ShellExecute() is what you're looking for.

John T
  • 23,735
  • 11
  • 56
  • 82
-1

Never use system() in Windows ! Just redirect i/o handles.