I need to send data from child processes to parent. Some of this data is HTML, plain text, etc. but it may also be necessary send image data, zip file data, etc.
As I understand it, anonymous pipes use the child process standard input and standard output. Conventionally stdin and stdout only convey textual data: would there be any problem with sending non printable characters using this mechanism?
There is no relation between anonymous pipes and stdin/out. As one process has only one stdin/out, you could create only one anonymous pipe per process that way, which sounds stupid, doesn't it? You can redirect stdin/out of a child process to the pipe, yes. But you don't have to, if the child process is able to report itself by another means (like logfile or network activity). A call to CreatePipe gives you reading and writing handles and it's up to you how you use them. Sending arbitrary binary data is indeed possible. Anonymous pipe is in no way different from named pipe in that respect.
Even if you do choose to use stdin/stdout redirection to pass the pipe handle(s) to the child process, you shouldn't have any problems provided the child process uses the Windows API to send the data rather than the C runtime library functions.
That is, WriteFile will work perfectly, but printf would not be a good idea.
You can use GetStdHandle to get the handle(s) to the pipe(s) for use with the Windows API functions.
Related
On Unix-like operating systems, the file descriptors (file handles) used for things like pipes and sockets are small integers. It's common for a parent process to communicate with its child process by opening a pipe, socket or file at a particular file descriptor number. The number will either be agreed upon by the programmers of the parent and child program, or passed to the child program via the command line or environment variables. The child can then access the inherited file descriptor using the same number as the parent.
Is there a convention for passing handle numbers in a similar way on Windows? As far as I can tell, the relevant MSDN articles only talk about such conventions for the "standard" file handles (standard input, standard output, standard error). What would be a robust and idiomatic way to do something like "pass a pipe on file descriptor 3" as we sometimes do on Unix?
The MSDN article on Inheritance says (emphasis mine):
An inherited handle refers to the same object in the child process as it does in the parent process. It also has the same value and access privileges.
Does this mean that I can just cast the HANDLE value to an integer, convert that integer into a string and pass that string as a command line argument for the child process to parse and get the same handle back, and is this reliable or customary? Is there some other IPC mechanism that Windows programmers would normally use instead?
The main motivation for me would be to avoid temporary files and use pipes instead. This is conventional when all you have is stdin/stdout but less so when you have multiple pipes.
As I understand, on Windows, the process that creates a named pipe, owns the "server" handle (one side of the pipe).
Is it possible to split pipe creation from actually using it (opening it for reading and writing)?
I need to create a named pipe with one process, but use two other processes to open it for reading and writing.
But I'm concerned, that when the process that creates the pipe exits, the pipe gets removed from the file system.
Named pipes exist solely because of the sort of scenario you're talking about.
With anonymous pipes (see CreatePipe), it is necessary that there be a "factory" somewhere that creates the pipe, and then at least one of the handles is handed off to a "client" somewhere (within the same process or not).
With named pipes (see CreateNamedPipe), it is not necessary to have the "factory" which creates and distributes the handles. Instead, the "server" side of the named pipe directly does a CreateNamedPipe with the correct pipe name, and the "client" side of the named pipe directly uses CreateFile with the pipe name to open the client side of the named pipe. Each side deals with its error conditions appropriately. If implemented correctly, no additional coordination is necessary.
If your application requires a "factory" process for the named pipe (it shouldn't), then you'll have to figure out your own way to provide the handles to the "client" processes in such a way that the pipe is not destroyed in the interim. Or you can use the pipe name instead of distributing the handles, but you may have to explicitly coordinate between the processes using something like a named event (see CreateEvent).
If this doesn't answer your question, please update your question with more details.
I'm writing a program that communicate with its child process using anonymous pipe. And I want to know if there are contents in the pipe for me to read. Because calling ReadFile for an empty pipe would result in halting.
The child process is another software so I can't change it. I can only redirect its i/o.
You can use the PeekNamedPipe function to examine the state of the pipe without blocking.
I am writing a win32 app which is using the namedpipe for inter-process communication. When one process is trying to writeFile, it will write the structure (tell other process how many bytes and other info), then it will write the actual data by calling WriteFile again.
The other process, when it is reading, it read the first msg, and then read the second msg based on the information got from the first msg.
My questions are:
If the server process is writing the data, but the client process hasn't read it yet, is it possible to lost the first msg when the client is reading? Example, when the server is calling WriteFile at the second time to write actual data, will the previous msg was overwritten?
Is there any best solution to use waitforsingleobject to sync?
Thanks
A pipe is a little like a real pipe -- when you write more to the pipe, it doesn't overwrite what was already in the pipe. It just adds more data to the pipe that will be delivered after the data that you previously wrote to the pipe.
I rarely find WaitForSingleObject useful for a pipe. If you want to block the current thread until it receives data from the pipe, you can just do a synchronous read, and it'll block until there's data. If you want to block until there's input from any of a number of sources, you usually want WaitForMultipleObjects or MsgWaitForMultipleObjects, so your thread will run when any of the sources has input to process.
The only times I can recall using WaitForSingleObject on a pipe were with a zero timeout, so the receiver would continue other processing if there was no pipe input, and every once in a while check if the pipe has some data to process. While it initially seems like PeekNamedPipe would work for this, it's really most useful for other purposes -- though it might work for you, to read the header data and figure out what other code to invoke to read and process the entire message.
Having said all that, I feel obliged to point out that I haven't written any new code using named pipes in quite a while. I can think of very few situations in which I'd even consider them today -- I'd almost always use sockets instead.
I know I can call the AttachConsole and GetStdHandle kernel32 functions to access the console screen buffers of a different console process, but if this process has its input/output/error redirected to a file or device, how can I get handles to those redirected locations instead?
To put it clear: I don't have control on the application I'm trying to attach to, which is provided by a third party, so my chances with IPC are little.
GetStdHandle will honour any redirection and return the redirected handle;
The standard handles of a process may be redirected by a call to
SetStdHandle, in which case GetStdHandle returns the redirected
handle.
The link also describes how to request the originals.
You can use CreateRemoteThread to insert code into the other process and call GetStdHandle from there. You'll then need to use DuplicateHandle to make a copy of the handle in your own process.
Keep in mind that anything you do with that handle will affect the handle in the target process, which could cause unexpected problems. If both processes attempt to read from the standard input stream, for example, you won't be able to predict which one will see what part of the input, and if both processes write to the standard output stream the output might be overlapped in random ways or one set of output might overwrite the other.