An Original Idea

because all great software begins with an original idea

Simple Inter-Process Communication In VB.Net

Posted by anoriginalidea on August 9, 2007

 

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).

Links

13 Responses to “Simple Inter-Process Communication In VB.Net”

  1. Damjan said

    Good tutorial. Tnx.

  2. Hubert Licman said

    Very usable example. You too much help me. Thanks.

  3. Mark Nunn said

    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!

  4. Mark,

    Simply add a reference to “System.Runtime.Remoting” and ipc remoting bliss will be yours.

    Have fun!

  5. David Leland said

    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

  6. Steve Schoonover said

    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

  7. 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

  8. wos said

    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

  9. wos said

    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.

  10. Keith Thompson said

    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

  11. Bobbie said

    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.

  12. Mitch said

    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.

  13. 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

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>