简体   繁体   中英

How to access an inherited anonymous pipe HANDLE, other than stdout, stderr & stdin, in Windows?

I am trying to receive data from a child process over an anonymous pipe in Windows. I know how to do this using standard I/O streams but these are being used for other purposes. I also know how to do this in Linux or OSX using fork() , pipe() and execv() .

In Windows, you can create a pipe with CreatePipe() and make one end not inheritable with SetHandleInformation() . Then for stdout and stderr you can pass STARTUPINFO , with hStdOutput or hStdError set, to CreateProcess() to pass the other end to the child. After the call to CreateProcess() the parent most close it's handle to the child's end of the pipe. This is all explained in detail in Creating a Child Process with Redirected Input and Output on MSDN. However, I have not found a way to pass a HANDLE , other than via stderr, stdout or stdin, to the child.

I've tried converting the HANDLE to a string with something like this:

std::ostringstream str;
str << hex << "0x" << handle;
std::string handleArg = str.str();

And then passing it as a command line argument and converting it back to a HANDLE , which is just a void * in the child process. Although the child process apparently inherits the pipe HANDLE the actual value of the HANDLE must be different than in the parent because passing it this way fails to work.

I know I can use a named pipe to do this but it seems it should be possible to do this with anonymous pipes.

So how can I pass a pipe HANDLE to a child process in Windows?

Update1: Sample code in this MSDN article seems to indicate that, at least with socket handles, you can pass them as a string to the child.

Update2: Turns out I made a mistake. See my answer below.

Turns out you can pass a HANDLE to a child process as a command line argument by converting it to string and then, in the child process, back to a HANDLE (which is just a void * ). Sample code using a HANDLE to a socket can be found here .

To make this work you need to make sure you follow Creating a Child Process with Redirected Input and Output closely. It's important that you close the child process's end of the pipe after calling CreateProcess() and get all the inheritance settings right.

Note, I tried passing the HANDLE as a string on the command line before but I was doing it wrong. My mistake was in passing the HANDLE as an int to boost::iostreams::file_descriptor() which made it treat it as a file descriptor instead of a Windows HANDLE .

Why not use the method shown here ?

Call the GetStdHandle function to get the current standard output handle; save this handle so you can restore the original standard output handle after the child process has been created.

Call the SetStdHandle function to set the standard output handle to the write handle to the pipe. Now the parent process can create the child process.

Call the CloseHandle function to close the write handle to the pipe. After the child process inherits the write handle, the parent process no longer needs its copy.

Call SetStdHandle to restore the original standard output handle.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM