views:

142

answers:

4

Is there any WinAPI WinExec analog in boost (c++) libraries? I need to run executable from my program, and pass parameters to it. Should I use any other cross-platform libraries for this, or handle myself what OS my program is compiled for?

+4  A: 

What is wrong with system(), which is part of standard C++? See http://www.cplusplus.com/reference/clibrary/cstdlib/system.

anon
Thanks. It is suitable. I don't have lot of practice in programming, so ask such stupid questions.
Heisenberg
Still, system should be avoided, since it spawns a new shell for no reason, doesn't provide useful error codes and its behavior is in general not quite predictable (it depends completely from the spawned shell).
Matteo Italia
@Matteo Whether the creation of a new shell is a good or bad thing is debatable (and actually the C++ and C standards don't say this must happen - some platforms may not have a "shell"), but system() is the only standard way of executing another executable - popen and the exec/spawn functions are not available on all platforms.
anon
@Matteo There is this thing here called an "answer". Please post your rant as one.
anon
Ok, moving the whole rant to an answer. :)
Matteo Italia
A: 

You might want to take a look at this question regarding popen() on win32: popen

dicroce
+1  A: 

There's a library that I believe is trying to get into boost called Boost.Process. You'll have to find a download for it, probably in sandbox or whatnot.

Noah Roberts
+2  A: 

My opinion is that you should use the APIs/syscalls provided by the various platforms you wish to support, or use some kind of abstraction layer (the Boost.Process library, mentioned by Noah Roberts, may be an idea) to avoid dealing with platform-specific details.

I strongly disagree with using the system function because it isn't intended to start a process you specify, but instead it's supposed to pass the string you specified to the "system default shell" or "command processor" (if any). This has several drawbacks:

  • resource wastage; instead of a process now (usually) you are spawning two, one of which (the shell) is useless for your final objective (starting the process you want). This is usually negligible, but may be noticeable on systems where processes aren't lightweight objects (Windows) if they are running low on resources.
  • useless confusion; several security suites I've dealt with warn every time an unknown/untrusted process starts a new process; instead of just displaying a warning, now the security suite will display two of them (and you're making the first one quite unclear);
  • unpredictability of the result; the platform-agnostic system's documentation could be replaced without much loss with "undefined behavior" - and actually it is quite like that. Why do I say this? Because:
    • first of all, there's not even a guarantee that system has some meaning on the current platform, as there could be no "default shell" at all. But this is an extreme case that isn't usually a problem - and that can be also caught quite easily (if(system(NULL)==0) there's no shell); the real problem is that
    • in general, you don't have idea about what shell is the "default shell", and how it parses its input; on Linux it will usually be /bin/sh, on Windows it may be command.com as well as cmd.exe, on another OS it will be still another thing. So, you aren't sure about, e.g., how to escape spaces in the path, or if you should quote the path; heck, you don't even know if such shell requires some special command to start executables!
    • More fun: you don't even know if the call is actually blocking: you know that by the time system will return the shell will be terminated, but you don't know if the shell will wait for the spawned process to end; concrete example: cmd.exe doesn't wait for GUI executables to end before returning, while on Linux GUI executables are executables like all the others and don't have such special treatment. In this case you'll have to create a special case for Windows, and make a command string like start /wait youexecutable.exe - hoping that the version of the interpreter still (or yet, depending on the version of Windows) supports that syntax. And IIRC start has different options on Windows 9x and Windows NT family, so you won't even be sure with that.
    • It's not enough: you aren't even sure if the application has been started: the system return value is relative to the command interpreter return code. As far as system is concerned, if a shell is started the call succeeded, and there ends what system considers an error.
    • Then you're left with the error code of the shell - about which, again, we don't know anything. Maybe it's a carbon-copy of the error code of the last executed command; maybe it is an error code relative just to the shell (e.g., 1 = last command executed, 0 = last command was invalid), maybe it's 42. Who knows?

Since in a good application you'll want, at least, to know if the call is blocking/nonblocking, to get a meaningful exit code (the one actually returned by the application you started), to be sure if the application has been started, to have meaningful error codes in case things went wrong, system most probably doesn't suit your needs; to earn any of these guarantees, you have to go with platform-specific hacks or with non guaranteed assumptions, wasting all the cross-platform "compatibility" of system.

So, I'll state it again: use the system calls provided by the various platforms (e.g., fork+exec on POSIX, CreateProcess on Windows), which specify exactly what they are guaranteed to do, or go with third party abstraction code; the system way is definitely not good.

Matteo Italia