Click here to Skip to main content
13,148,427 members (67,382 online)
Click here to Skip to main content
Add your own
alternative version

Stats

8.7K views
423 downloads
7 bookmarked
Posted 24 Mar 2016

Anonymous Pipes Made Easy

, 24 Mar 2016
Rate this:
Please Sign up or sign in to vote.
A simple and convenient wrapper class for Anonymous Pipes in C#

Example Pic

Introduction

Sometimes, you just need to be able to talk to your application.

It should be that easy, shouldn't it? Let's say you have a few applications running as part of your solution, and you just want your main application to be able to tell the others to shut down. Or maybe you want to start one up, have it run in the background, and then pass back some useful information. Or maybe you have a Windows Service running on the same machine as a desktop application, and you need them to be able to comunicate with each other, and you really don't want to (and shouldn't) resort to using tcp/ip.

Anonymous pipes is the solution to these problems. Implementing them can be a little tricky though. The aim of the AnonymousPipes class in this example project is to make using them as easy and intuitive as I believe they should be in the first place.

Background

I've built several tcp/ip communications librabies, and I find myself going to them a lot to solve problems with communication between different applications in my solutions. I sometimes find myself tempted to communicate with different applications on the same machine through these libraries when I shouldn't, because it would be easy... But there really is no reason to go through the network card and drop your message on the network, when it will only be picked up by the same network card and computer but for another application. It's a network security problem as well as needless network bandwidth usage.

The right way to go here is IPC (Interprocess Communication) - Anonymous Pipes in particular (as opposed to NAMED pipes, which I won't discuss here), because we only want communication between running applications on the same PC or server.

There is a bit of setup involved in using Anonymous Pipes, and there is also the niggling limitation that an Anonymous Pipe is a one way communication channel... so if you want TWO way communication between your main and child applications, you need to set up two pipes.

This seemed like a perfect oppertunity to write a wrapper class that handles all this setup and detail for me... and when I was done, it occurred to me that I could probably have found what I was looking for here on CodeProject. I was surprised to discover that there isn't (or my search didn't bring one up) an example of Anonymous Pipe usage here for C#.

Using the code

In the example project, I am simply checking to see if there are any command line arguments when the windows forms application starts. If there aren't, then I am assuming that this instance is going to be the pipe SERVER, so I immediately start another instance of the application and pass the two pipe handles (input and output pipes) to the new instance as command line args.

The second instance starts up and discovers that it does indeed have some command line args, so it assumes it is a pipe CLIENT. It reads the first argument which is the two handles of the pipes created by our first instance, and connects to the two pipes.

Below is an example of instantiating the AnonymousPipes wrapper class. I think that may be a little confusing to look at, so I'm going to go into a little detail about this instantiation:

pipe = new AnonymousPipes("Server end of the pipe.", Application.ExecutablePath, "additionalArgs=your_own_command_line_args_here", delegate(String msg)
                {
                    this.Invoke((MethodInvoker)delegate()
                    {
                        this.lbTextIn.Items.Add(msg);
                    });
                }, delegate()
                {
                    // We're disconnected!
                    try
                    {
                        if (!this.IsDisposed)
                        {
                            this.Invoke((MethodInvoker)delegate()
                            {
                                this.lbTextIn.Items.Add("Client disconnected!");
                            });
                        }
                    }
                    catch (Exception) { }
                });

The AnonymousPipes class is instantiated differently depending on who is instantiating it: the pipe SERVER, or the pipe CLIENT.

If the pipe SERVER is instantiating it, then the AnonymousPipes wrapper class has some initial setup to do - including starting the child application and passing it the command line argument containing the handles of the two pipes.

Because it's a wrapper class, and I wanted to make it as reusable as possible, I'm using delegates to get incoming text from the wrapper class. I could have used a named delegate and passed the name of the function as a parameter to the AnonymousPipes constructor, but one of the things I love about C# is how easy and convienient it is to use anonymous delegates and lambdas, and I guess I just couldn't help myself.

The AnonymousPipes constructor that is used by the pipe server application looks like this:

public AnonymousPipes(String pipeName, String clientPath, String cmdLineArgs, CallBack callback, DisconnectEvent disconnectEvent) 
{ 
}

The pipeName, clientPath and cmdListArgs parameters are fairly obvious, I think: pipeName is a name you give this pipe so you can keep track of it if you were to add the AnonymousPipes object to a list. You get the name of this object by calling .GetPipeName().

the clientPath parameter is exactly that - the complete path of the client application that will be started and passed the command line arges you provide, and the pipe handles. The pipe handles are the first command line arg, and that command line argument is passed to this wrapper class after instantiation in the client application.

The callback delegate had the following signature:

public delegate void CallBack(String msg);

This is used to pass incoming text from the pipe to YOU. Any incoming text will arrive this way. You should use a function with the proper signature (something like private void YourFunction(String msg) { }), or an anonymous inline delegate the way I did. In this example project, I'm simply shoving everything that comes in into a listbox so you can see it.

disconnectEvent is another delegate. It will trigger if your child application dissconnects from the pipe. Use this to do any clean up you need to in the eventuality that your child disconnects or shuts down.

In the client application, the wrapper class is instantiated like this:

                AnonymousPipes pipe = new AnonymousPipes("Client end of the pipe.");
                pipe.ConnectToPipe(theArgs[0], delegate(String msg)
                {
                    this.Invoke((MethodInvoker)delegate()
                    {
                        lbTextIn.Items.Add(msg);
                    });
                }, delegate()
                {
                    // We're disconnected!
                    this.Close();
                });

When instantiating the wrapper class in the client, just pass the name. Then call ConnectToPipe(), as seen above. The delegates should be familiar, and work exactly the same way they did in the pipe server instantiation.

History

None yet. this is brand new!

License

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

Share

About the Author

pdoxtader
President Doxtader Industries LLC
United States United States
I've been in IT for the last 20 years in one capacity or another - always as either a network engineer or a developer... or both. At the moment I have an IT consultancy in Long Island, NY offering software development and network engineer services.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionClient/Server Projects Pin
opti9991-Jun-16 7:43
memberopti9991-Jun-16 7:43 
AnswerRe: Client/Server Projects Pin
pdoxtader1-Jun-16 7:52
memberpdoxtader1-Jun-16 7:52 
GeneralRe: Client/Server Projects Pin
opti9991-Jun-16 8:05
memberopti9991-Jun-16 8:05 
GeneralRe: Client/Server Projects Pin
pdoxtader1-Jun-16 9:05
memberpdoxtader1-Jun-16 9:05 
GeneralRe: Client/Server Projects Pin
pdoxtader1-Jun-16 9:17
memberpdoxtader1-Jun-16 9:17 
Questionreacting to text received messages Pin
opti9991-Jun-16 2:44
memberopti9991-Jun-16 2:44 
AnswerRe: reacting to text received messages Pin
pdoxtader1-Jun-16 2:49
memberpdoxtader1-Jun-16 2:49 
GeneralRe: reacting to text received messages Pin
opti9991-Jun-16 3:12
memberopti9991-Jun-16 3:12 
GeneralRe: reacting to text received messages Pin
pdoxtader1-Jun-16 3:28
memberpdoxtader1-Jun-16 3:28 
GeneralRe: reacting to text received messages Pin
opti9991-Jun-16 3:51
memberopti9991-Jun-16 3:51 
GeneralRe: reacting to text received messages Pin
pdoxtader1-Jun-16 3:57
memberpdoxtader1-Jun-16 3:57 
GeneralRe: reacting to text received messages Pin
opti9991-Jun-16 4:08
memberopti9991-Jun-16 4:08 
GeneralRe: reacting to text received messages Pin
pdoxtader1-Jun-16 4:02
memberpdoxtader1-Jun-16 4:02 
GeneralRe: reacting to text received messages Pin
opti9991-Jun-16 4:11
memberopti9991-Jun-16 4:11 
GeneralRe: reacting to text received messages Pin
pdoxtader1-Jun-16 4:23
memberpdoxtader1-Jun-16 4:23 
GeneralRe: reacting to text received messages Pin
opti9991-Jun-16 4:25
memberopti9991-Jun-16 4:25 
QuestionServiceBus Pin
williams200028-Mar-16 22:40
memberwilliams200028-Mar-16 22:40 
AnswerRe: ServiceBus Pin
pdoxtader29-Mar-16 4:23
memberpdoxtader29-Mar-16 4:23 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.170924.2 | Last Updated 24 Mar 2016
Article Copyright 2016 by pdoxtader
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid