Simple Inter-Process Communication In VB.Net

Standard

image

There are plenty of articles around for inter process communication, using remoting, custom windows messages and named pipes.  In my .net career I think I’ve used all of them.  In this article I’ll outline a technique I’ll be using that I think is quite simple.

In .net Framework 2.0, Microsoft introduced the new System.Runtime.Remoting.Channels.Ipc   remoting channel , which provides one of the easiest (prior to using WCF) techniques.

In this example we have a single server process which is communicated to via client processes.

image

SharedInterfaces

Firstly, as with all remoting it is necessary to share a type that defines the api you desire between client and server processes.  One of the easiest things to do is to create an interface.

For the sake of this example, I created an assembly called “Shared Interfaces” containing an interface called “ICommunicationService”:

Public Interface ICommunicationService
Sub SaySomething(ByVal text As String)
End Interface

Server

image

For the Server in this example, I created a console application (it can be any sort of process).

The Server project contains two classes:

  • An implementation of ICommunicationService called “CommunicationService”
  • A Main that registers to CommunicationService class for acess

The CommunicationService class implements the interface and inherits from MarshalByRefObject :

Public Class CommunicationService
Inherits MarshalByRefObject
Implements SharedInterfaces.ICommunicationService

Public Sub SaySomething(ByVal text As String) Implements SharedInterfaces.ICommunicationService.SaySomething
Console.WriteLine(“The client said : ” & text)
End Sub
End Class

The main registers the type:

Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Ipc
Module Main
Sub Main()
Dim ipcCh As IpcChannel
ipcCh = New IpcChannel(“IPChannelName”)

ChannelServices.RegisterChannel(ipcCh, False)
RemotingConfiguration.RegisterWellKnownServiceType( _
GetType(CommunicationService), “SreeniRemoteObj”, _
WellKnownObjectMode.Singleton)

Console.WriteLine(“Press ENTER to quit”)
Console.ReadLine()
End Sub
End Module

Client

image

The client project is written as a Winform with a textbox and a button.  The button click contains this code:

Imports System.Runtime.Remoting
Imports System.Runtime.Remoting.Channels
Imports System.Runtime.Remoting.Channels.Ipc
Public Class Form1

Private Sub cmdSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdSend.Click
Dim ipcCh As New IpcChannel(“myClient”)
ChannelServices.RegisterChannel(ipcCh, False)

Dim obj As SharedInterfaces.ICommunicationService = _
DirectCast(Activator.GetObject(GetType(SharedInterfaces.ICommunicationService), _
“ipc://IPChannelName/SreeniRemoteObj”), SharedInterfaces.ICommunicationService)
obj.SaySomething(txtText.Text)

ChannelServices.UnregisterChannel(ipcCh)
End Sub

End Class

The code basically gets a reference to the remote object and invokes the “SaySomething” message, passing through a value.

As you can see, it doesn’t take much code to communicate between processes.

Improvements

Further improvements to the code will involve ensuring security (making sure that only desirable client processes are calling).

Download a zip file containing the entire project for Visual Studio 2008.

Links

26 responses »

  1. This article looks great but unfortunately I can’t seem to get it to work with .NET framework v3.5 and Visual Basic 2008.

    It fails on the line ‘Imports System.Runtime.Remoting.Channels.Ipc’ as it cannot find ‘Ipc’. I wonder what I am doing wrong!

  2. Great article and sample code. I have a requirement to create an “Instant Messenger” application and as such need the “Server” and “Client” pieces to reside within a single program. Can’t seem to find the magic combination – any suggestions would be greatly appreciated.

    Dave

  3. This example worked fine for my purposes. I did use the console app for the Server portion like this example shows.

    What I would like to do is use a Windows Form instead of a console app to display my values passed through the SaySomething method. When I attempt to create a Form and startup my application as a Windows Application (not a console app) I am unable to reference and modify the label on the Server form. I’ve determined the CommunicationService Class is a separate thread from the one launched through the Server form I’ve created.

    Is there a way to have this SaySomething method in the Server app reference the new Windows form I’ve created?

    Thanks for any help.

    Steve

  4. Hi Steve,

    There are a few ways to communicate between threads in this scenario.

    One way is to put a reference to your display form in a “Shared” variable, then use the “BeginInvoke” method on the form to update the text property.

    Another way is to store the “say” text in a collection, exposed as a shared variable, then use a timer on the Winform to periodically bind (read the data from) the collection if the data changes.

    Regards

    Julian

  5. Hey Dude!

    Great job, thank you very much!
    There is just one thing I can’t deal with – if you wanna combine server and client in one program, the code in the “SaySomething” method is done twice, ain’t it?

    Thanks for the help,

    wos

  6. Hey there!

    It’s me again – found a solution.
    Problem was that I was using windowsform – object in the “SaySomething” method.
    Sure it’s just fired by the server side, but as there are two instances of the program with the windowsform – object being public, my application did it once for the form in Instance I and then for form in instance II.

    If anyone needs the solution code, just mail.

    Nice evening to ya all.

  7. Hi,

    Sorry if this is a naive question… I’m just getting into this… I got everything working ok, but I need multiple clients to be able to send messages to the server, but if I try sending a message from a client, whilst the server is dealing with another, I get an exception. I’ve tried setting “WellKnownObjectMode.SingleCall”, to allow an instance per client (I think!), but I still get the same error. Do I need to / can I set up a range of ports to use? Do I need to set up the client to wait until the port is free? Any help would be very gratefully accepted

  8. I ran into alot of grief getting this to work on XP. Turned out what worked was

            Dim properties As IDictionary = New Hashtable()
            properties.Add("authorizedGroup", "Users")
            properties.Add("portName", "myClient")
            properties.Add("rejectRemoteRequests", True)
            Dim ipcCh As IpcChannel
            ipcCh = New IpcChannel(properties, Nothing, Nothing)
    

    instead of

            ipcCh = New IpcChannel("IPChannelName")
    

    I hope this saves someone else the 2 hours of grief I had trying to get it to work.

    Oh, and I also had to use

            ChannelServices.GetChannel("myClient")
    

    instead of

            Dim ipcCh As New IpcChannel("myClient")
            ChannelServices.RegisterChannel(ipcCh, False)
    

    on the receiving end.

  9. This is a great article, but I’m having some difficulties. I’ve followed your directions and got two applications communicating well. However, in the “SaySomething” sub, instead of a simple console.writeline command, I decided to call another subroutine that is in the code for one of my forms. This subroutine is attempting to change the form in some way — add text to a label, change the opacity of the form, whatever — however, I can’t seem to manipulate the form at all. Does anyone know why? PLEASE HELP.

  10. Hi Mitch,

    Applications written as Winforms or WPF have to have their UI elements (such as labels and textboxes) updated on the “UI Thread”.

    Because “Say Something” is invoked by a non-ui thread, you have to to “marshall” the update onto the ui thread.

    There are two ways to do this (as I noted in a previous comment):

    One way is to put a reference to your display form in a “Shared” variable, then use the “BeginInvoke” method on the form to update the text property.

    Another way is to store the “say” text in a collection, exposed as a shared variable, then use a timer on the Winform to periodically bind (read the data from) the collection if the data changes.

    Hope this helps

    Regards

    Julian

  11. i’m working in Win 7 64bit; Visual Studio 2008; Visual Basic

    and trying to recreate this project. When i run the program and click the command button, the line

    obj.SaySomething(Me.TextBox1.Text)

    produces an error saying:
    “Failed to connect to an IPC Port: The system cannot find the file specified.”

    Can you tell me what’s wrong?

    thanks
    mark c.

  12. Hello I get this error when trying to use the code:

    Cannot load type ‘someapp.SharedInterfaces.ICommunicationService, someapp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’.

    Any ideas why?

  13. Pingback: vb.net inter-process communication | Webmaster Forum Archive

  14. I appreciate the attempt but I wasted over an hour discovering that the examples presented here are incomplete and lead to an exercise in troubleshooting. I experienced each and every error described in the comments. I wonder if this post causes more confusion for novices like me than is reasonable. I also wonder why the post hasn’t been ammended. By the time I hit the last (unanswered) problem described in comment #15 from Miha I decided to abandon this post altogether, but not before leaving this message as a warning to others like me who are easily confused.

    • I’m sorry that you had so much trouble. If you’re still interested I have updated the article to include a link to the (now upgraded) Visual Studio 2008 project. I hope this helps you and anyone else who may be experiencing problems.

      The article is intended as a simple introduction to remoting. I recommend further reading on the subject before creating production code that uses these techniques. Please keep in mind that since .net 3.5, wcf provides a more modern alternative to remoting.

      Sorry for any inconvenience.

      Please note that comments included in this forum must be improved by me before they appear.

  15. Oops. I just went to download the project and I got some sort of 404/error.

    BTW: Thanks for the updated project. I appreciate it.

    I am trying to learn how a 64-bit process can communicate with a 32-bit process so that the 64-bit process can indirectly call functions in a 32-bit COM Component hosted in the 32-bit process. The 32-bit COM component can not be updated to x64.

  16. Hi,

    Thanks for this tutorial!
    The link to the VS2008 version leads to a 404. Could you repost it? I’m eager to try it!

    Thanks!

  17. Hi. I tryed to implement this example in vb 2010 and it works fine. My problem is very similar but i’m not able to solve it. I’ve two processes: the first with a timer that update the text field of a label each second; and the second that has only one button which ‘click’ event reads the value of the label of the first process. I tryed to make a shared interface in the timer form and to return the value of the label (similar to this example), but i read only 0. Can you help me???

    thanks,
    Pietro

  18. Hi people

    new to all this. i changed the server from a console to a form. i am able to get what is sent popping up as a message box on the server. the thing is i am trying to get it to change the text on a label instead of a message box popping up. i added a line to change the text on a label on the form to what has been received but it is just not happening! it is receiving the string that is sent as the message box is set to run after the label text change line.

    i have even tried putting in a line of code that will call a sub written in the form module itself to check a checkbox…. but that wont work!

    what is it that i am not doing?

    this is what i am trying to accomplish….

    1) change a label or button text, or even a variable or property using this tutorial and,
    2) cause procedures or events to run just by sending a string that a Select Case determines by what it receives.

    Thanks chaps!

  19. Thanks for this simple sample code.

    Works “straight out of the box” on Win7 32 bit with VS2010

    This has answered the question I have had after previously having trouble with the compiler not recognising the “ipc” in “Imports System.Runtime.Remoting.Channels.Ipc” for some reason.
    I have just spent a few hours searching for alternatives after initially being misled into believing the VB did not support the “ipc” interface directly, now I have this simple sample I can find out were I am going wrong with my original code.

    Thanks again

    (The alternative I was considering having to learn C#, its been many years since I have done any C++ even and I was not looking forward to having to relearn the C type syntax)

Leave a reply to Miha Cancel reply