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?
What is wrong with system()
, which is part of standard C++? See http://www.cplusplus.com/reference/clibrary/cstdlib/system.
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.
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 becommand.com
as well ascmd.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 likestart /wait youexecutable.exe
- hoping that the version of the interpreter still (or yet, depending on the version of Windows) supports that syntax. And IIRCstart
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 assystem
is concerned, if a shell is started the call succeeded, and there ends whatsystem
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?
- first of all, there's not even a guarantee that
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.