I´m writing two litle c++ apps that must communicate. First one will be a service which, every once in a while, must alert the user for something. Since a service cannot create windows I designed the app to be two separate executables.
The service will use a notifier to communicate.
The service needs only to send text messages to the notifier wich will show up a balloon at system tray.
I´m trying to use named pipes and I think I´m almost there, but not quite there. What I have so far is:
At the notifier side:
m_hInPipe = CreateNamedPipe(L"\\\\.\\pipe\\nhsupspipe", PIPE_ACCESS_INBOUND,
PIPE_WAIT, 1, 1024, 1024, 60, NULL);
Meaning I created a pipe named nhsupspipe, an inbound pipe.
At the service side:
if (!WriteFile(m_hOutPipe, "My message to the user?", 23, &escritos, &o))
std::cout << "ERROR: " << GetLastError();
Debugging I can see that it is all ok, the pipe is created and the WriteFile writes my 23 bytes to the pipe.
My question is: How, in the notifier side I´ll be able to read these bytes? Is there any message sent to the process? Do I have to write a handler for the pipe? Anything?
You need to use ReadFile or ReadFileEx (for Overlapped I/O) on notifier side typically in a thread or message loop. Also look at the documentation for CreateNamedPipe and WaitNamedPipe.
In this circumstance, I'd probably use RPC instead of raw named pipes. With raw named pipes, you have to parse the data from the client which introduces the possibility of security bugs. With RPC you can let RPC parse the data for you which decreases the chance of introducing an error.
Some simple snippets from the client (your service) & the server (the notifier) [Note: This is adapted from a project I've done a while ago which in turn was heavily "influenced" by the MSDN samples from CreateNamedPipe & co]:
Server side:
The client:
The Message mentioned above is a structure that will be your message, which you will probably want to pack.
Since in your scenario the client (the service) will probably be up & running before the server (the notifier) you'll need to have in place some kind of reconnection strategy on the client side.
And on a slightly different note you should consider carefully what Mr. Osterman said in his reply (even for nothing else but because he's Larry Osterman).
Not exactly the question, but another option is CreateEvent() and a memory mapped file.
If I were doing this, I'd have the service side do the
CreateNamedPipe
(outbound), and then callConnectNamedPipe
to wait for the notifier to connect.On the notifier side, I'd use
CreateFile
withFILE_FLAG_OVERLAPPED
. With that, the handle to the pipe will be signaled when data becomes available to read. Your notifier will (presumably) also be maintaining a GUI, so you'll probably want to have it callMsgWaitForMultipleObjects
in its event loop. That will wait for messages to be processed or data coming in on the pipe to be processed. That will work almost like a normal event loop, except that its return value is slightly different fromGetMessage()
-- it'll returnWAIT_OBJECT_0
if your handle is signaled, orWAIT_OBJECT_0 + 1
if you have a message (assuming you only have it wait on the one handle -- it's reallyWAIT_OBJECT_0 + N
, whereN
is the number of handles you had it wait on). For the most part, it's like a normalPeekMessage
orGetMessage
loop -- wait 'til there's something to do, do it, wait again.