With C++ how do i launch an exe/process with stdin stdout and stderr? I know how to do this in .NET and i remember using popen in the past but popen seems to allow stdin OR stdout not both and not all 3.
I need this for windows but a linux solution is welcome as i'll need it for the same project in the future.
You shoud use CreateProcess from WinApi. It takes as argument an object of struct STARTUP_INFO type. You can set hStdin, hStdout, and hStderr fields of the object to redirect those streams of child process to file handles you want (file, pipe, socket...)
A portable solution would be boost.process
(Note: this has been proposed as a Boost library, and released under the same license terms, but not officially accepted. See also Where is Boost.Process?)
I had troubles with spawning processes and reading or writing to their stream, but then I discovered a great C++ library which is very very convenient.
This open-source project is called tiny-process-library and was created by eidheim (a big thanks to him).
A small platform independent library making it simple to create and
stop new processes in C++, as well as writing to stdin and reading
from stdout and stderr of a new process.
Features
No external dependencies
Simple to use
Platform independent
Read separately from stout and stderr using anonymous functions
Write to stdin
Kill a running process (SIGTERM is supported on Unix-like systems)
Correctly closes file descriptors/handles
I am sharing this here because I first come to this thread before finding the library several hours later, so I hope it can save some time for further readers.
Related
I have a string command I'd like to execute asynchronously while writing to its input and reading its output. Sounds easy, right, the devil is in the cross-platform. I'm targeting both MSVC/Win32 and gcc/Linux and obviously want to write the minimum amount of platform-specific code. My google-fu has failed me, I get too much noise for my queries, so I started with what I know.
popen - nice and easy, returns FILE* that is easy to consume everywhere. But here's what MSDN have to say about _popen:
If used in a Windows program, the
_popen function returns an invalid file pointer that causes the program
to stop responding indefinitely.
_popen works properly in a console application. To create a Windows
application that redirects input and
output, see Creating a Child Process
with Redirected Input and Output in
the Platform SDK.
and so popen is out of the question (edit: because I'd like my code to work in GUI application). The Windows way to do it is in my opinion rather ugly and verbose. I could live with platform specific spawn code but I'd want at least the I/O code to be the same. Here, however, I hit a wall between the WinAPI HANDLEs and C FILE*, and int file descriptor. Is there a way to "convert" a HANDLE to FILE* or int fd or vice-versa? (Google failed me once more on this one, all the keywords I tried are way overused)
Is there better way to do the whole thing with little platform-specific code?
External libraries are not out of the question, however dependency maintenance is a pain, especially so on multiple platforms so I'd like to reduce dependencies. I didn't find such library in boost also.
Just for the record, what worked for me in the end. On Windows/MSVC, CreatePipe() + CreateProcess() as outlined here, using _open_osfhandle() followed by _fdopen() to get FILE* to the process input and output. On Linux/GCC, nothing new here, creating pipe()s; fork() then dup2() the pipes; exec(); fdopen() on the relevant file descriptors. That way, only the process spawning code is platform dependent (which is ok, as on Windows I'd like to control additional STARTUPINFO parameters), writing input and reading output is done through standard FILE* and related functions.
Give libexecstream a whirl. It's cross platform, and allows you to trap the input, output and error streams of a process asynchronously as C++ style streams.
I've used it on Linux, Darwin and Windows and it seems to work. It's also pretty lightweight so integrates into projects with little pain, and has a pretty open BSD licence. I don't think there's any way around using a library (other than writing your own variations for each platform).
for converting windows HANDLEs to C file descriptors use _open_osfhandle http://msdn.microsoft.com/en-us/library/bdts1c9x%28VS.71%29.aspx
EDIT: this example once helped me aswell with a similar problem:
http://www.halcyon.com/~ast/dload/guicon.htm
I want to run an application in c++ and read its stdout and write t stdin in windows? No popup should be generated.
Can I do it easily using windows services?
I found that I maybe able to do this with POCO, but do I really need this?
Is there solution in std library for this?
You can spawn a child process and then gain access to its stdin and stdout pipes. You have to use WinAPI to achieve this. See example here: http://msdn.microsoft.com/en-us/library/ms682499(v=vs.85).aspx
You may use Qt and it's QProcess class to read/write child process output/input.
I have a string command I'd like to execute asynchronously while writing to its input and reading its output. Sounds easy, right, the devil is in the cross-platform. I'm targeting both MSVC/Win32 and gcc/Linux and obviously want to write the minimum amount of platform-specific code. My google-fu has failed me, I get too much noise for my queries, so I started with what I know.
popen - nice and easy, returns FILE* that is easy to consume everywhere. But here's what MSDN have to say about _popen:
If used in a Windows program, the
_popen function returns an invalid file pointer that causes the program
to stop responding indefinitely.
_popen works properly in a console application. To create a Windows
application that redirects input and
output, see Creating a Child Process
with Redirected Input and Output in
the Platform SDK.
and so popen is out of the question (edit: because I'd like my code to work in GUI application). The Windows way to do it is in my opinion rather ugly and verbose. I could live with platform specific spawn code but I'd want at least the I/O code to be the same. Here, however, I hit a wall between the WinAPI HANDLEs and C FILE*, and int file descriptor. Is there a way to "convert" a HANDLE to FILE* or int fd or vice-versa? (Google failed me once more on this one, all the keywords I tried are way overused)
Is there better way to do the whole thing with little platform-specific code?
External libraries are not out of the question, however dependency maintenance is a pain, especially so on multiple platforms so I'd like to reduce dependencies. I didn't find such library in boost also.
Just for the record, what worked for me in the end. On Windows/MSVC, CreatePipe() + CreateProcess() as outlined here, using _open_osfhandle() followed by _fdopen() to get FILE* to the process input and output. On Linux/GCC, nothing new here, creating pipe()s; fork() then dup2() the pipes; exec(); fdopen() on the relevant file descriptors. That way, only the process spawning code is platform dependent (which is ok, as on Windows I'd like to control additional STARTUPINFO parameters), writing input and reading output is done through standard FILE* and related functions.
Give libexecstream a whirl. It's cross platform, and allows you to trap the input, output and error streams of a process asynchronously as C++ style streams.
I've used it on Linux, Darwin and Windows and it seems to work. It's also pretty lightweight so integrates into projects with little pain, and has a pretty open BSD licence. I don't think there's any way around using a library (other than writing your own variations for each platform).
for converting windows HANDLEs to C file descriptors use _open_osfhandle http://msdn.microsoft.com/en-us/library/bdts1c9x%28VS.71%29.aspx
EDIT: this example once helped me aswell with a similar problem:
http://www.halcyon.com/~ast/dload/guicon.htm
I want to execute a certain batch file and redirect its console output to a text control in visual c++ or redirect the console output at the same time the logs/echo are showing.
Basically, you have to make the run process to write to a pipe, and to read the output of this pipe.
[EDIT] I know how SciTE does that (you can take a look at the source: win32/SciTEWin.cxx, ExecuteOne function), I searched a slightly more generic way, found How to spawn console processes with redirected standard handles from Microsoft itself.
If you seach CreatePipe PeekNamedPipe CreateProcess keyword, for example, you might find other examples.
Another option is to use Boost.Process (Boost.Process is not (yet) an official Boost C++ library. It must be downloaded and installed separately).
The example "Child.4 - Reading from a child using asynchronous I/O" shows how to redirect the output of the child process into a C++ stream (and later access the content).
Example "Child.4 - Reading from a child using asynchronous I/O" show how to use Boost.Process togehter with Boost.Asio to access the childs I/O asynchronous.
The advantages of this method is, that Boost.Process supports the Windows API and POSIX API.
If elegance is not a priority then a really simple solution might be to redirect the output to a file, and then read in the file contents.
I have a project that I thought was going to be relatively easy, but is turning out to be more of a pain that I had hoped. First, most of the code I'm interacting with is legacy code that I don't have control over, so I can't do big paradigm changes.
Here's a simplified explanation of what I need to do: Say I have a large number of simple programs that read from stdin and write to stdout. (These I can't touch). Basically, input to stdin is a command like "Set temperature to 100" or something like that. And the output is an event "Temperature has been set to 100" or "Temperature has fallen below setpoint".
What I'd like to do is write an application that can start a bunch of these simple programs, watch for events and then send commands to them as necessary. My initial plan was to something like popen, but I need a bidrectional popen to get both read and write pipes. I hacked something together that I call popen2 where I pass it the command to run and two FILE* that get filled with the read and write stream. Then all I need to do is write a simple loop that reads from each of the stdouts from each of the processes, does the logic that it needs and then writes commands back to the proper process.
Here's some pseudocode
FILE *p1read, *p1write;
FILE *p2read, *p2write;
FILE *p3read, *p3write;
//start each command, attach to stdin and stdout
popen2("process1",&p1read,&p1write);
popen2("process2",&p2read,&p2write);
popen2("process3",&p3read,&p3write);
while (1)
{
//read status from each process
char status1[1024];
char status2[1024];
char status3[1024];
fread(status1,1024,p1read);
fread(status2,1024,p2read);
fread(status3,1024,p3read);
char command1[1024];
char command2[1024];
char command3[1024];
//do some logic here
//write command back to each process
fwrite(command1,p1write);
fwrite(command2,p2write);
fwrite(command3,p3write);
}
The real program is more complicated where it peeks in the stream to see if anything is waiting, if not, it will skip that process, likewise if it doesn't need to send a command to a certain process it doesn't. But this code gives the basic idea.
Now this works great on my UNIX box and even pretty good on a Windows XP box with cygwin. However, now I need to get it to work on Win32 natively.
The hard part is that my popen2 uses fork() and execl() to start the process and assign the streams to stdin and stdout of the child processes. Is there a clean way I can do this in windows? Basically, I'd like to create a popen2 that works in windows the same way as my unix version. This way the only windows specific code would be in that function and I could get away with everything else working the same way.
Any Ideas?
Thanks!
On Windows, you invoke CreatePipe first (similar to pipe(2)), then CreateProcess. The trick here is that CreateProcess has a parameter where you can pass stdin, stdout, stderr of the newly-created process.
Notice that when you use stdio, you need to do fdopen to create the file object afterwards, which expects file numbers. In the Microsoft CRT, file numbers are different from OS file handles. So to return the other end of CreatePipe to the caller, you first need _open_osfhandle to get a CRT file number, and then fdopen on that.
If you want to see working code, check out _PyPopen in
http://svn.python.org/view/python/trunk/Modules/posixmodule.c?view=markup
I think you've made a very good start to your problem by using the popen2() function to abstract away the cross-platform issues. I was expecting to come and suggest 'sockets', but I'm sure that's not relevant after reading the question. You could use sockets instead of pipes - it would be hidden in the popen2() function.
I am 99% sure you can implement the required functionality on Windows, using Windows APIs. What I cannot do is point you to the right functions reliably. However, you should be aware the Microsoft has most of the POSIX-like API calls available, but the name is prefixed with '_'. There are also native API calls that achieve the effects of fork and exec.
Your comments suggest that you are aware of issues with availability of data and possible deadlocks - be cautious.