The wyDay blog is where you find all the latest news and tips about our existing products and new products to come.
2 months ago we released wyBuild & wyUpdate v2.5. This release adds a free automatic updater control for C# & VB.NET apps. And because we wanted to keep things simple we left the wyUpdate.exe to do all the hard work (checking, download, installing) in the background while the AutomaticUpdater control is visible on your apps main form.
We wanted the AutomaticUpdater to be able to control the update steps, view progress, and cancel the updating. But we also wanted to keep all the updating logic in the wyUpdate.exe. For this to be successful we needed a way for the AutomaticUpdater control to talk to wyUpdate.exe while its running.
Inter-Process communication is a fancy computer science way of saying processes that can talk to each other. Google Chrome uses IPC to communicate between tabs of the browser & plugins. Its a simple way to keep parts of your program isolated from crashes.
For instance, if a tab of Google Chrome crashes only that single tab is killed. The rest of your tabs will continue to function normally.
Now that you know what inter-process communication is, let me tell you the worst ways to do it.
Inter process communication using named pipes is what Google Chrome uses and what we use for wyUpdate and the AutomaticUpdater control. Let me teach you about named pipes.
Like Marios pipes?
Exactly like Marios pipes. Except, instead of jumping Mario through the pipe, you push data through the pipe:
You can transfer any data between your processes. So what data should your transfer? The answer is it depends. The rule of thumb is to keep it short, and keep it simple. Heres what we do with the named pipe between wyUpdate and the AutomaticUpdater control sitting on your application:
With this simple setup the AutomaticUpdater control thats on your application is completely isolated from wyUpdate.
Download the named pipes C# source. It works with .NET 2.0, 3.0, 3.5 on Windows 2000 Windows 7.
There are two files that do all the work: PipeServer.cs and PipeClient.cs. We use the PipeServer.cs file inside wyUpdate, and we use the PipeClient.cs file inside the AutomaticUpdater control.
Also included in the zip file is a simple messaging program to demonstrate communication between two separate processes:
Tell me what you think in the comments. I want to hear from you.
Subscribe to our blog's RSS Feed or follow Wyatt (CEO of wyDay) on Mastodon (@wyatt@hachyderm.io) to keep up-to-date with our latest posts.
Did you consider using anything in System.Runtime.Remoting? With .NET remoting the client can call functions on the remote object as if it was a local object. Its also easy to change the underlying IPC mechanism to TCP, Pipes, Http, or shared memory.
I had considered using System.Runtime.Remoting, however we had a few requirements that the Remoting namespace didn't match. Namely we needed the ability for Admin processes to talk to Non-admin processes & vice versa. This is a real problem on Vista & Windows 7. Plus, we also needed the Server to detect when a client disconnect & the clients to know when the server disconnected (even if a message saying as much wasn't sent).
The problem with the Remoting namespace is that it's too high-level for our particular problem. But I suppose it's fine if you don't need these problems solved.
What are the differences between named pipes and message queues?
That's what I was talking about when I mentioned SendMessage / PostMessage. There are a lot of differences between named pipes and message queues. The one reason I didn't use message queues (besides the inability for non-admin processes to talk to admin processes) was the message queue deadlock problem.
In short, message queues are a really poor way to do IPC on Windows.
Msmq is not the only message queue that can run on windows
I wasn't aware of any other message queuing system on Windows. I based all my research on non-third party IPC systems available on Windows 2000+ which work with .NET 2.0+.
I suppose you could use some POSIX wrapper to support Unix style message queues, but these implementations likely use named pipes or sockets as the backend.
MSMQ (like Paco was referring to) and SendMessage/PostMessage (like Wyatt is talking about) are completely different things.
MSMQ is total overkill for a simple lightweight job like the example.
IE8 is multi-process as well (before Chrome, BTW :-). Do you know which approch IE use?
The process model in IE8 is described in detail in both Scott Hansleman's post & on the IEBlog. Neither of the posts mention what IPC model IE8 uses. However, and it might be just me, but Hanselman's wording when he mentions Google Chrome using named pipes seems to imply IE8 also uses named pipes:
Great article and awesome work.
WCF also supports named pipes......
Thanks Steven.
Yes, it does. But wyUpdate & the AutomaticUpdater control are written for .NET 2.0, and WCF came with .NET 3.0. It would have cost us customers & caused our existing customers a hassle if we decided to up the requirements to .NET 3.0.
Plus, my solution is easier to use.
Excellent post, and thank you very much for providing the source code.
I am unsure what use I will have for named pipes in any of my current projects, but I am almost certain this will be extremely beneficial some day down the line!
Cheers!
What license is associated with the code? Is it okay for commercial use?
My pleasure, Tom.
I didn't state it explicitly, but the source code is licensed under the BSD license. I should probably add that to the zip file.
So yes, you can use it in commercial products.
Excellent, thank you very much!
I found something interesting while using this code. I wanted to use IPC for sending parameters to another application (along the lines of allowing only a single instance), but found that if I tried to do this without any user interaction, it would become very flaky and it only received two messages of the many that I sent. Then, I figured out why. You need to have the thread sleep (I have it set to a second). I assume this doesn't happen in your provided demos because at least 1 second passes by the time you move the mouse from the Connect button to the Send button.
SendMessage(...) returns a boolean. True if the message was sent successfully, false if it wasn't. To avoid the sleeping, just put the SendMessage in a simple loop.
This way the thread will only sleep on failure.
Great article, you've got yourself a new subscriber
Your implementation has race conditions. The server can read and write on the same pipe at the same time with two different threads.
This isn't a race condition, but a bug as the result of not properly support overlapped named pipes. I'll upload our fixed version later.
Someone posted this elsewhere, but I figured I would let you know here, there seems to be a bug in your Listen thread in ConnectNamedPipe,
"If hNamedPipe was opened with FILE_FLAG_OVERLAPPED, the lpOverlapped parameter must not be NULL. It must point to a valid OVERLAPPED structure. If hNamedPipe was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the function can incorrectly report that the connect operation is complete."
Thanks for spotting that Andy. I'll have a fix up a little later this week.
another option for those using .net 3.5 is:
System.IO.Pipes.NamedPipeServerStream
System.IO.Pipes.NamedPipeClientStream
WCF can be overkill some times.
Great piece of code, find it useful for some ideas I'm trying to explore.
I noticed here in the comments that there are some bugs/race conditions, is the actual source code still buggy or is it the corrected version?
Anyway thanks for the code and keep up the good work :)
Hey Angelo,
The race conditions can be temporarily be solved using something as simple as
I'm working on a proper fix, but it might be a while. The code above will simply try again if a transfer fails due to a race condition.
As far as the "OVERLAPPED" bug, yes I've fixed it, but I haven't uploaded the latest version yet. I'll upload it either tonight or tomorrow.
Sorry to bother...just checking if the fixed version was uploaded.
Can you help?
Thanks again
Angelo
Not yet. We're still running it through our tests. I'll update the post when I've uploaded it.
Great article and comment responses.
The timestamps on files within the download zip file suggest that you have not uploaded your update? Do you plan to?
Hey Jim,
Yes we plan to. In the meantime the while(){} code block a couple of comments above should work fine.
> Wyatt O'Day - March 28th, 2010 at 10:04 pm
>
> Thanks for spotting that Andy. Ill have a fix up a little later this week.
More than 7 months later - still not fixed, neither for the "OVERLAPPED" bug, nor for the race conditions.
Will you update it or not?
Thanks.
Yes. We've already fixed this internally. I'll be uploading it later (in N days where N is less than infinity).
In the meantime just use the hack-fix I posted before:
This will work fine for any reasonable Client/Server communication.
It is fixed. I haven't posted it yet because I've been spending the past 7 months growing our business. Plus, this ranks pretty low on the list of priorities especially considering that the hack-fix solves this problem.
It will be posted when I get a bit of free time to package it up nicely.
The race condition isn't really a race condition. It's just a bug from not properly supporting overlapped named pipes. See the temporary fix above.
Is the code updated yet. I'd like to give it shot.
Not yet. Our workaround (the retry while loop) does almost exactly what the correct implementation does internally. We plan to release the fixed version, but it's not a priority.
If you're using .NET 3.0+ use the WCF (Windows Communication Foundation).
Still no update? Surely it can't take a year to update such a simple example
Why are the calls to Stream.Read and Stream.Write referencing a buffer of large size (256 bytes) but only reading/writing the first 4 bytes of the buffer?
It reads much more than 4 bytes. Search for all references to the "readBuffer" variable in the code.
Your blog has really inspired me to really rethink the way I run my site. I want to let you know I appreciate your hard work.
To serialize/deserialize we can use MemoryStream instead of ASCIIEncoding, isn't it? That way we can communicate custom objects too and not only strings.
I need to communicate with different processes, I tried with WCF but Dynamic objects are not supported in .Net 3.0. ObjectResolver is supported only in .Net 4.0. I need to use .Net 3.0 hence i was searching for a simple implementation of the named pipe. Thanks for sharing.
You can serialize using whatever method you want. We prefer using a custom serialization that we can "de-serialize" from other languages and platforms.
Beautiful work. Thank you.
Fabulous article!!! This website just keeps me coming back. I enjoyed the labor that you put into it as well as get pleasure from reading through all of the articles. Hi and thanks a bunch as well as keep the nice work up!
Dear wyatt,
i would like your post. i can communication betweeen pc in lan? it 's only work for process in one pc?
To communicate between PCs you need to use the network stack. IPC is only for communication between processes on 1 machine.