Click here to Skip to main content
Click here to Skip to main content

.NET Interprocess Communication Revisited

By , 4 Jan 2010
 

Introduction

The XDMessaging library provides an easy-to-use, zero configuration solution to same-box communications. It provides a simple API for broadcasting and receiving messages across application and process boundaries.

Version 1.0 was originally developed to use low-level Windows Messaging and to offer a performant solution for Windows Forms based applications. However, the restriction in using Windows Messages is that it does not provide a way to communicate with non-Forms based applications such as Windows Services which don't have their own message pump.

Version 2.0 now extends the library further, and provides a second file IO based transport mode for messaging. The new IOStream mode can be used to communicate with Windows services, console apps, and continues to work with Forms based applications.

The library allows the use of user-defined pseudo channels through which messages may be sent and received. Any application can send a message to any channel, but it must register as a listener with the channel in order to receive. In this way, developers can quickly and programmatically devise how their applications will communicate with each other best, to work in harmony.

Advantages

The XDMessaging library offers some advantages over other IPC technologies like WCF, .NET Remoting, Sockets, NamedPipes, and MailSlots. To begin with, the library does not require a server-client relationship as there is no physical connection between processes.

With XDMessaging, messages can be broadcast by multiple applications, and instantly received by multiple listeners in a disconnected fashion. MailSlots offer the closest match to this functionality; however, I found this had a few limitations. Although messages are also disconnected, there is no way to peek at a message, and as soon as the message is read, it is removed from the MailSlot. It's great for broadcasting messages, but limited to a single client for receiving the message. The other limitation is that messages are not instant, and requires polling of the MailSlot.

It's also worth noting that most of the existing IPC implementations require the opening of specific ports and a somewhat painful configuration of settings to make them work. With XDMessaging, there is no configuration; the API determines where messages are sent, and which messages are received using pseudo channels. The disadvantage is that communication is limited to a single machine, so for network communication, other IPC technologies such as WCF are much more suited.

Using the Library

To use the library, create an instance of a IXDBroadcast and use this to send a message to a named channel. You can then create an instance of IXDListener to receive messages on a particular channel. The channels are arbitrary strings chosen to represent a channel, and are not case sensitive.

Before creating the broadcast and listener instances, you must first decide which transport mode you want to use for the library. There are two modes as follows, and each has advantages over the other.

Transport Modes

  • IOStream: This uses file based IO to broadcast messages via a shared directory. A FileSystemWatcher is used within listener classes to monitor changes and trigger the MessageReceived event containing the broadcast message. This mode can be used in Windows Services, console applications, and Windows Forms based applications. Channels are created as separate directories on the file system for each channel. The temporary directories should be accessible by all processes, and there should be no need for manual configuration.
  • WindowsMessaging: This uses the WM_COPYDATA Windows message to copy data between applications. The broadcast implementation sends the Windows messages directly to a hidden window on the listener instance, which dispatches the MessageReceived event with the copied data. Channels are created by adding/removing Windows properties. This offers the most performant solution for Windows Forms based applications, but does not work for Windows Services, console apps, or other applications without a message pump.

Note: Messages broadcast using a particular mode can only be read by applications using a listener in the same mode. For example, IOStream listeners cannot read messages broadcast in the WindowsMessaging mode.

See the included sample applications for more information on using the library in Windows Forms applications or within a Windows Service.

Examples

Example: Sending a message in a particular mode:

// Create an instance of IXDBroadcast using IOStream mode
IXDBroadcast broadcast = XDBroadcast.CreateBroadcast(XDTransportMode.IOStream);

// or create an instance of IXDBroadcast using WindowsMessaging mode
IXDBroadcast broadcast = XDBroadcast.CreateBroadcast(XDTransportMode.WindowsMessaging);

// Send shutdown message to a channel named commands
broadcast.SendToChannel("commands", "shutdown");

Example: Listening for messages on a particular channel:

// Create our listener instance using IOStream mode
IXDListener listener = XDListener.CreateListener(XDTransportMode.IOStream);

// or create our listener using WindowsMessaging mode
IXDListener listener = XDListener.CreateListener(XDTransportMode.WindowsMessaging);

// Register channels to listen on
listener.RegisterChannel("events");
listener.RegisterChannel("status");
listener.RegisterChannel("commands");

// Stop listening on a specific channel
listener.UnRegisterChannel("status");

Example: Handling the messages:

// Attach an event handler to a listener instance
listener.MessageReceived+=XDMessageHandler(this.listener_MessageReceived);

// process the message
private void listener_MessageReceived(object sender, XDMessageEventArgs e)
{
 // e.DataGram.Message is the message
 // e.DataGram.Channel is the channel name
 switch(e.DataGram.Message)
 {
  case "shutdown":
             this.Close();
      break;
 }
}

Further Reading

History

  • 12 Dec 2009: Initial release
  • 16 Dec 2009: Optimized performance
  • 4 Jan 2010: Adding network propagation support via MailSlots

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

TheCodeKing
Architect
United Kingdom United Kingdom
Member
Mike Carlisle - Technical Architect with over 10 years experience in a wide range of technologies.
 
@TheCodeKing

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
NewsXDMessaging 4.0memberTheCodeKing3 Feb '13 - 10:24 
A new version 4.0 is now available on NuGet with support for Amazon SQS/SNS http://nuget.org/packages/XDMessaging/4.0.0.1[^]

GeneralMy vote of 5memberTheFigmo30 Jan '13 - 6:46 
Holy IPC, Batman! This library rocks! SUPER SIMPLE to implement and it just flat out works - first time - every time.
 
NOTE: The article has a link to the author's web page in the 'Further Reading' section. Be sure you go there and download the latest version. Not the version here on CP.
Questionregarding Interprocess CommunicationmemberTridip Bhattacharjee13 Nov '12 - 19:51 
hi i am not very familiar with what is Interprocess Communication. can you tell me any example of Interprocess Communication.
tbhattacharjee

QuestionRandom Crash [modified]memberstormyseasailor3 Oct '12 - 23:42 
Hello,
 
I am getting a WinIOError telling me that the access to 'Global\\XDMailSlotListener.System.PropagateBroadcast.XDIOStreamBroadcast' is denied.
 
I tried running my application with admin rights but it didn't work.
 
When debugging, it's crashing randomly and it's not pointing me towards the sources (event though I included and referenced the lib sources) ...
 
Here's the stack trace :
 
à System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
à System.Threading.Mutex.MutexTryCodeHelper.MutexTryCode(Object userData)
à System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
à System.Threading.Mutex..ctor(Boolean initiallyOwned, String name, Boolean& createdNew, MutexSecurity mutexSecurity)
à System.Threading.Mutex..ctor(Boolean initiallyOwned, String name, Boolean& createdNew)
à TheCodeKing.Net.Messaging.Concrete.MailSlot.XDMailSlotListener.MailSlotChecker(Object state)
à System.Threading.ThreadHelper.ThreadStart_Context(Object state)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
à System.Threading.ThreadHelper.ThreadStart(Object obj)

 
Here's my code :
 
                private static string IPC_CHANNEL_GUI = "MyChannel";
                Program.broadcast = XDBroadcast.CreateBroadcast(XDTransportMode.IOStream);
                listener = XDListener.CreateListener(XDTransportMode.IOStream);
                listener.MessageReceived += new XDListener.XDMessageHandler(Program.OnMessageReceived);
                listener.RegisterChannel(IPC_CHANNEL_GUI);</pre>
 
Can anyone tell me what I am doing wrong ?
 
Thanks,
 
Jonathan

modified 4 Oct '12 - 8:38.

AnswerRe: Random CrashmemberTheCodeKing4 Oct '12 - 11:26 
Hi,
 
Thanks for providing the info. If you're not using network propagation features can you bypass the error by disabling the network mailslot listener. By default all listeners participate in network propagation in order to ensure network messages are re-dispatched locally. By disabling this feature the mutex throwing the exception will not be used.
 
// create listener without participating in network propagation
listener = XDListener.CreateListener(XDTransportMode.IOStream, true);
 
As to why the exception is occurring it's not entirely clear. Is it a forms application? What version of Windows are you running on? Are you processing a high volume of messages?
 
Mike

GeneralRe: Random Crashmemberstormyseasailor5 Oct '12 - 23:18 
Hi Mike,
 
It seems I wasn't using the latest version. Mine didn't have a CreateListener taking two arguments.
I tried again with the one from nuget and it worked :
http://nuget.org/packages/XDMessaging[^]
 
With this version (3.0), it works with or without telling the listener to exclude network messages.
 
Thanks for this great piece of work,
Cheers,
Jonathan
GeneralMy vote of 5membersun19915 Sep '12 - 16:55 
Very neat! 3.0 is even better!
Thanks.
QuestionBrilliant!memberCleveland Mark Blakemore30 Jan '12 - 19:56 
Best C# implementation of Mailslots on the Code Project. Blows the second closest runner-up away completely.
GeneralRunning in terminal server session: mutex problemmemberJ.Buysrogge17 Feb '11 - 2:29 
Hi,
 
We are running a database application that makes use of XDMessaging to communicate with a tray application. We use standard Windows Messaging as transport.
 
However, when 2 instances of this application are started on the server (win2k3) by 2 different clients (winxp), the tray application crashes on the 2nd client with the exception message "xxxx has stopped working due to unhandled exception: System.UnauthorizedAccessException".
 
Now I traced this back to the function XDMailSlotListener.cs->MailSlotChecker(). I think the new Mutex() call throws this error. I placed a try/catch around it and I can positively verify that it now handles the exception.
 
Checking with SysInternals/ProcExp reveals a mutex called "Global\XDMailSlotListener.....". This mutex is created by the first winxp client, and when the second starts it bumps into an existing global mutex.
 
The MailSlotChecker is entered regardless of creating a new XDBroadCast with or without propagate network.
 
Is MailSlotChecker really needed here, as I'm running XDMessaging for Windows Messaging transport only ?
 
Any comments would be great.
 
And thanks for the great library.
Pika
GeneralRe: Running in terminal server session: mutex problemmemberPika8117 Feb '11 - 3:46 
Btw, I changed:
 
private const string mutexNetworkDispatcher = @"Global\XDMailSlotListener";
 
to
 
private const string mutexNetworkDispatcher = @"Local\XDMailSlotListener";
 

and now no problems (so far). Do you think it's a safe solution ?
 
Thx,
Pika
GeneralRe: Running in terminal server session: mutex problemmemberTheCodeKing17 Feb '11 - 11:58 
Hi,
 
The Mutex should be Global as only one process can read from the MailSlot on the same box. If it's set to local you will have multiple processes trying to access the MailSlot for every listener process on the machine.
 
Mike

GeneralRe: Running in terminal server session: mutex problemmemberTheCodeKing17 Feb '11 - 11:49 
HI,
 
Thanks for raising the issue I'll take a look when I get a chance. It's caused by one process creating the MailSlot which the other then doesn't have permissions to read. I think I've seen the error before, possibly due to one process being elevated and the other not (is this the case?).
 
The reason MailSlot is used in the implementation for Windows Messaging and IOStream is to allow for network propagation defined on any remote broadcasters. In this case messages are re-thrown to other listeners on the same box using Windows Messaging or IOStream when a MailSlot is received. As only one process can pick up the message (limitation of MailSlot) the idea is that one process will always act as the MailSlot receiver for network propagation. If that process is killed, another listener takes on the role. If there are no listeners then MailSLots can be ignored.
 
I hope that makes sense.
 
Mike

GeneralRe: Running in terminal server session: mutex problem [modified]memberPika8118 Feb '11 - 2:09 
Mike, thanks for te clarification.
 
Running both instances in elevated (Run as... Administrator/without restricted access), eliminates the problem.
 
However, this is not something we can ask of our clients, that run in a restricted sandbox environment.
 
Since the communication is only 1-to-1, database app to tray app and vice versa, is there a way to avoid the MailSlot mutex ?
I have tried to create an XDBroadCast instance for windows messaging, with propagateNetwork set to false, but that doesn't
seem to make any difference.
modified on Friday, February 18, 2011 8:58 AM

GeneralRe: Running in terminal server session: mutex problemmemberTheCodeKing18 Feb '11 - 3:18 
PropagateNetwork only effects whether the messages on your local box are additionally dispatched to other machines on the local network. The flag doesn't affect the ability to receive messages from other machines (that are propagating), which is why the MailSlot is in use despite your local broadcast settings set to false.
 
It sounds like catching the exception and failing silently is the solution in your case, as you don't care about this functionality. In the next version I'll also add a flag on the listener to enable op-out of network propagated messages.

GeneralRe: Running in terminal server session: mutex problemmemberPika8118 Feb '11 - 3:48 
Ok, thanks for the help.
GeneralRe: Running in terminal server session: mutex problemmemberTheCodeKing25 Feb '11 - 23:59 
Hi,
 
I'm just looking into this now. Could you try changing the code to the following and see if it fixes your issue? I'm testing on Windows 7 and can't reproduce it locally.
           
MutexSecurity accessControl = new MutexSecurity();
SecurityIdentifier sid = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);
accessControl.SetAccessRule(new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow));
using (Mutex mutex = new Mutex(true, mutextKey, out isOwner, accessControl))
 
Thanks,
Mike

GeneralRe: Running in terminal server session: mutex problemmemberTheCodeKing26 Feb '11 - 1:24 
Alternatively I've upload version 2.1.0.0 which should resolve your issues. Let me know if it doesn't.
 
http://xdmessaging.codeplex.com/releases[^]

GeneralRe: Running in terminal server session: mutex problemmemberPika812 Mar '11 - 3:56 
Hi Mike,
 
Sorry for the late response. I'll try your new binary and I'll let you know what the results are asap.
 
Regards
GeneralRe: Running in terminal server session: mutex problemmemberPika812 Mar '11 - 5:18 
Just took a look, and I'm happy to say that your modification works.
 
One small remark, I took a look at the code and noticed you now catch System.UnauthorizedAccessException from mutex.WaitOne().
The place where it actually throws the exception in my case was the mutex constructor. So I had to place a try catch around the
using() directive.
 
You can also see this in help docs: http://msdn.microsoft.com/en-us/library/bwe34f1k(VS.85).aspx
The WaitOne() method does not throw this kind of exception, but the constructor does.
 
Anyway, thanks for taking a look at it !
GeneralRe: Running in terminal server session: mutex problemmemberTheCodeKing3 Mar '11 - 2:49 
Hi thanks for the update, and pointing out my bug. I put the extra catch in in-case the permissions didn't resolve the issues. Hopefully the UnauthorizedAccessException should never occur now, but you're right the catch needs to be moved.
 
I'll update the code and put up a new release.

GeneralRe: Running in terminal server session: mutex problemmemberTheCodeKing5 Mar '11 - 10:17 
The exception handling is now fixed in 2.1.0.2.

GeneralSupport for WPFmemberdyna1manning23 Dec '10 - 8:21 
Hi, I noticed you mentioned compatibility with windows form based applications. So this cannot be used for WPF applications?
GeneralRe: Support for WPFmemberTheCodeKing23 Dec '10 - 11:00 
Hi, the library pre-dates WPF which is the reason it only refers to Windows Forms. There's no reason it shouldn't work with WPF.

Generalcode kingmemberMubi | www.mrmubi.com30 Jul '10 - 12:36 
good stuff.
Mubshir Raza Ali
^^^^^^^^^^^^^^^^^^^^
http://www.mrmubi.com

QuestionIssue with elevated programs?memberdemeester10 Apr '10 - 0:56 
I noticed that Windows Messaging and Mailslot Messaging do not work between a program that is elevated (or "run as Administrator") and a program that is not. Is this observation correct and if so, can it be overcome (except from elevating the whole set)? Btw, this has been observed in Windows7.
Confused | :confused:

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 4 Jan 2010
Article Copyright 2009 by TheCodeKing
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid