RSS 2.0 Feed
RSS 2.0


Atom 1.0 Feed
Atom 1.0

  Communication between applications via Windows Messages 


qt8gt0bxhw|20009F4EEE83|RyanMain|subtext_Content|Text|0xfbffc50000000000b000000001000200

At times I'll build a suite of related, but separate applications. Even though each application is a separate executable, I like to be able to integrate the applications so they can work together. Sending messages between your applications is a great way to do just that. I build this kind of thing into my apps often, but really think nothing of it since the code is hidden in a base form class. I was asked by someone how to communicate with other apps so I decided to blog a sample to answer the question (which is where most of my posts come from it seems).

There are two parts to communicating via messages. First, you need to be able to listen, or filter the messages. Second, you need to be able to send the messages. Let's look at sending them first.


Sending Windows Messages via the SendMessage API

Sending Windows Messages is easy. First of all you'll need to p/invoke the SendMessage Win32API. Add the DllImport to your code and you're ready to go.

[DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern IntPtr SendMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam);

With the DllImport added, you'll need to know a little bit about what the parameters are about. For this example, we'll just focus on the first two. The first is the handle for the application that you'll be sending the message to, the second is the message you're sending. I'll blog at a later date about how to use the wParam and lParam to send additional data with the message.

For this example we'll define our own messages to send to our applications. We could define messages that mean a number of different things to our app, but we'll just define a simple generic one that we'll send to other instances of our sample app. Choose a unique int and assign it to a const to give it some meaning. Something like this:

private const int RF_TESTMESSAGE = 0xA123;

Now for sending the message. Let's say in our sample application we want to send this message to all other running instances of our app. What we'll need to do is get all running instances of our application and send this message to each of them. An easy enough task. Take a look at the code.


//get this running process
Process proc = Process.GetCurrentProcess();
//get all other (possible) running instances
Process[] processes = Process.GetProcessesByName(proc.ProcessName);

if (processes.Length > 1)
{
    //iterate through all running target applications
    foreach (Process p in processes)
    {
        if (p.Id != proc.Id)
        {
            //now send the RF_TESTMESSAGE to the running instance
            SendMessage(p.MainWindowHandle, RF_TESTMESSAGE, IntPtr.Zero, IntPtr.Zero);
        }
    }
}
else
{
    MessageBox.Show("No other running applications found.");
}


That will cover sending the message to all running instances of our app (assuming we have multiple instances of the app running). Now we just need to set up the ability to receive and act on the messages.


Receiving Windows Messages by overriding the WndProc

To listen for the message we need to override the base Form class' WndProc method (Well, the WndProc is really part of the Control base class, but since the Form class is in it's downstream we'll use it there). To use the WndProc we need to override it so we can look for our specific messages. Once we do that the rest is a peice of cake. We just test for our message and do whatever action we need to perform. In this sample, we'll just indicate that we received the message by adding a line to a ListBox.


protected override void WndProc(ref Message message)
{
    //filter the RF_TESTMESSAGE
    if (message.Msg == RF_TESTMESSAGE)
    {
        //display that we recieved the message, of course we could do
        //something else more important here.
        this.listBox1.Items.Add("Received message RF_TESTMESSAGE");
    }
    //be sure to pass along all messages to the base also
    base.WndProc(ref message);
}


That's it. Now you can start up multiple instances of the app and send messages from one of them to all the other running instances. You can also download a sample project that includes the code from this post. Start up multiple instances of the app and send messages to the other running instances.

 Download sample project: SendMessageDemo.zip


(Click to view sample)
    




                   



Leave a comment below.

Comments

  1. Shukri 7/8/2004 4:27 AM
    Gravatar
    Gotta say it - thanks for the code! Does exactly what I wanted and clearly explained. Ppl like you keep my programming world turning.

  2. Ryan Farley 7/10/2004 11:09 AM
    Gravatar
    Shukri, Thanks for the compliment! Glad the code helped!

    -Ryan
  3. Henrik Nielsen 8/6/2004 7:07 AM
    Gravatar
    Absolutely a supreme article. I would though be very glad to see a followup explaining how to use wParam and lParam, especially how to marshall strings.
  4. A. Hobbs 12/27/2004 9:27 PM
    Gravatar
    Great article. Very very helpful.
  5. Phil Ceetham 1/10/2005 12:14 PM
    Gravatar
    Very helpful.

    I need to pass a file name (path) to another app (that I wrote also). Have you publiished the way to pass a string?
  6. James Brooks 2/4/2005 4:10 AM
    Gravatar
    I've been searching for a solution like this for the past 2 hours, the rest of the solutions I've found have been overly complicated and in the end, quite useless. This is simple, effective and EXACTLY what i've been after. Thanks!
  7. Gus Apostol 2/11/2005 1:53 PM
    Gravatar
    Thanks for posting this article. I've been looking quite a bit for this information. This really helped me out!!
  8. Samir Parekh 2/27/2005 9:09 PM
    Gravatar
    How should i send string as lparam using the above technique, and we should try using RegisterMessage() API to get a message registered prior to its use to avoid clashes with pre-Existing messages
  9. Prabu 3/8/2005 11:37 AM
    Gravatar
    This is great and this example works fine..

    But I need little more than this, I need to send message to an application that is iconized in the Tray.. buy the MainWindowHandle returns 0 and the message is not reaching..

    I tried with sample notepad.exe and still i I get MainWindowHandle as 0.

    Please advise.

    Thank you
    Prabu
    prabu@vontlin.net
  10. Simon Soosai 3/18/2005 10:36 AM
    Gravatar
    This is great, saved me few hours of my investigation. Keep up the good work man.

    Cheers
    Simon Soosai
  11. Mouhannad 3/20/2005 8:23 AM
    Gravatar
    Hi,

    is there any reference to guide me sending messages to famous applications like MS Word for example ( if i want to close open save ....)

    thanks in advance

    Mouhannad
    mhnd_79@hotmail.com
  12. Daniel 4/10/2005 3:58 PM
    Gravatar
    I have a questions regarding to this.
    It is possible to do communicatton between web applications?

    Thanks in advance
  13. Anjaneyullu Tamma 5/24/2005 7:45 AM
    Gravatar
    Is it possible to send messages from a nt service to an application when there is no one logged on to the machine?

    Thanks in advance.
    Anjaneyullu Tamma
    anjaneyullu@tamma.us
  14. Ryan Farley 5/24/2005 7:52 AM
    Gravatar
    Anjaneyullu,

    I don't see how that could be possible. To send a message to an app the app must be running (ie: there is someone logged in). Also you need the application/window handle - which would only exist if the window is open (again requires someone is logged on).

    -Ryan
  15. Ryan Farley 5/24/2005 7:55 AM
    Gravatar
    Daniel - see the answer to Anjaneyullu, same applies to you (ie: no, this would not work to communicate between web apps since there is no actual window - just a running process)

    Mouhannad - To communicate with Word, you are better off using Word automation and controlling Word via it's object model.

    -Ryan
  16. Fleasoft 7/25/2005 6:52 AM
    Gravatar
    Great job! This really helps. Like others, I'd look forward to a future article that discovers lParam and wParam.
  17. SecurityCoder 11/14/2005 11:21 AM
    Gravatar
    Hello

    For sending a message to another window, I think you need to use WM_CHAR parameter and send the string charachter by charachter.

    I know VB.NET code for this... You can send a command (message) to cmd.exe by this code:

    Const WM_CHAR As Int32 = &H102

    Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
    ByVal hwnd As Int32, _
    ByVal wMsg As Int32, _
    ByVal wParam As Int32, _
    ByVal lParam As Int32) As Int32

    Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Int32



    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click


    'get handle to app window to send message to
    wndh = FindWindow("ConsoleWindowClass", vbNullString)
    If wndh = 0 Then
    wndh = System.Diagnostics.Process.Start("cmd.exe").MainWindowHandle.ToInt32
    End If


    'get string from textbox
    Dim str As String = TextBox1.Text

    'string to byte array
    Dim B() As Byte = System.Text.Encoding.Default.GetBytes(str)

    Dim I As Integer

    For I = 0 To str.Length - 1
    SendMessage(wndh, WM_CHAR, B(I), 0)
    Next I

    SendMessage(wndh, WM_CHAR, 13, 0)
    End Sub



    End Class




    This code checks first for existance of cmd.exe... If not exists, loads one... Then sends your command that exists in TextBox1 to cmd.exe window and finally send CHR(13) for ENTER.

    Regards
  18. Yang 1/12/2006 8:22 AM
    Gravatar
    Very nice article.

    Could you add your C/C++ version?

  19. punit 2/16/2006 2:02 AM
    Gravatar
    tu yeda hai
  20. Ted 2/22/2006 10:10 PM
    Gravatar
    Came across this site via a link from a Microsoft forum. Not up on this subject. Just a bit over my head. I have a related problem and wondering
    if the solution here can be adapted for it. If so, I can handle it if you can keep it simple, in newbies terms - step by step.

    I think the solution to my basic problem has common, popular and practical applications. I already possted the essence of the following elsewhere and really hoping someone could be kind enough to help with this:

    14:00 / 23-Feb-06

    On a simple Win XP Pro Home Network ( Comp #1 downstairs / Comp #2 upstairs), how
    can I send a message or file from #1 to #2's DeskTop (and vise versa), without

    getting too complicated - like using "Remote Desktop", et. al., a feature which

    allows full computer access and thereby may overly compromise security.

    There may also be up to 2 other comp's connected to our network at some times and
    with which similar com's is desirable. No computer should have access to messages
    not specifically intended for them.

    All computers are also connected to Internet most of the time and we have "SHARE"

    enabled for some folders under C:\. We prefer not to bother with all sorts of User
    Accounts and Passwords either.

    We just want a simple "com's" feature (akin to, let's say, "Messenger" or to an

    "Intercom" system) whereby we, for example, are each aware of a "COMS" folder on
    each other's DeskTop that we check regularly for mutual messages sent to us from
    1 or more other computers.

    This would be one approach. There should also be some feature included to create

    awareness of new message arrival. If the "COMS folder" on DeskTop could be made
    to "flash" or create some pleasant repetitive "sound" (either automatically or via
    remote instruction) when a new message enters the folder, so much the merrier to
    attract our mutual attention.

    A simple method would be best. We are not Programmers but know how to create DOS
    Batch files and "copy" and modify VB macros (in Word), if that's of any use.

    Installing an Intercom would not do the job as we would like to keep a record of
    our messages on the comps.

    Can anyone help?

    Ted...( tedoniman@hotmail.com[ignore_this_suffix] )


  21. Ryan Farley 2/22/2006 10:19 PM
    Gravatar
    While I don't usually respond to questions posted which are not relevant to the article topic (The "messages" referred to by the article are not the same kind of "messages" you are talking about), I wonder why standard Windows (or MSN) Messenger won't work for what you need? It does *exactly* everything you mention you want. Sending messages, along with a flashing and sound played upon arrival. Sending files between computers, etc. Why not just use it? Anyway, I'm afraid you won't find much else here that can help - after all this is a places for programming topics only.

    Good luck.

    -Ryan
  22. Garry 4/11/2006 12:39 PM
    Gravatar
    Great article, thanks for posting it.

    Is there a way to have the process listen of the Message instead of the Window? In my case, the window is hidden and the Process.MainWindowHandle is zero when the window is hidden. I need to be able to send a message to the process to activate the main window.

    THanks in advance for your reply,

    Garry
  23. { public virtual blog; } 5/25/2006 2:41 PM
    Gravatar
    I started this blog in August of 2003, almost 3 years ago. I've made 176 posts in those 3 years. I don't post too often to my blog because I'm not all that big on posting stories about my kids, wife, dog, etc - although those do come in every now and then. Anyway, even when I have lulls where I am not posting as much, my traffic seems to stay pretty consistent. I'm actually amazed at how much traffic I get, especially when I consider how often I get around to posting (big thanks to all the visitors over the years)
  24. hardik vaishnav 6/27/2006 12:19 PM
    Gravatar
    hi,
    I tried your given code but it is giving me an error at this line.
    Process[] processes = Process.GetProcessesByName(proc.ProcessName);

    and error is :

    An unhandled exception of type 'System.InvalidOperationException' occurred in system.dll

    Additional information: Couldn't get process information from remote machine.

    so please help me with this.

    thanks,
    -hardik
  25. Kevin 7/18/2006 12:02 PM
    Gravatar
    Did you write that article on how to use the other two parameters from sendMessage?
  26. pete 8/22/2006 8:04 PM
    Gravatar
    is it posble to communicate messages across multiple networked computers (i do not want to use Remoting or RMI)?

    p.MainWindowHandle is not designed for Remote Computer. Is there any other way around this limitation?

    Basically I have to applications running on different computers on LAN. I need to have some kind of synchronization betwn them (messages seems to be a perfect approach)

    Best Regards

    - Solidus
  27. Giorgio 9/5/2006 8:06 AM
    Gravatar
    Hello i used similar code but all vb.net 2005

    1. I look for the open processes wich have the same name of my application.

    2. In case none is found i open my application.

    3. in case i find 1 open i send a personalized message to the window to open a proprietary document.

    I use Message.Create(handle, WM_MYCUSTOMMESSAGE, 0, MyIntegerCode)

    Then i have the same ovverride of wndproc subroutine in the main form of my application , ready to parse the message.

    My problem is that this message is not parsed!! It is like if mainwindowhandle and the main form of my application are not the same thing!

    So how can i get my main form handle ? Or , how can i write a routine to trap messages to the application handle ? I also tried implementing a class to filter system messages but it does not work with the messages i send to the application (probably only messages from window o.s. fire this function)..

    Thank you for your help
    Regards
    Giorgio
  28. Siamak 11/23/2006 12:33 PM
    Gravatar
    I can't marshal a structure through send message! What is wrong?
    (I receive wrong data in second app)

    //APP1 - Sending data structure through LParam
    //...
    //data is a structure with 2 values: int,double
    lParam = Marshal.AllocCoTaskMem(Marshal.SizeOf(data));
    Marshal.StructureToPtr(data, lParam, true);
    SendMessage(AppHandle, WM_MY_MESSAGE, IntPtr.Zero, lParam);
    Marshal.FreeHGlobal(lParam);

    //App2 - Receiveing data
    protected override void WndProc(ref Message m)
    //......
    case WM_MY_MESSAGE:
    AStruct data= (AStruct)Marshal.PtrToStructure(m.LParam, typeof(AStruct));
    break;







  29. emre 11/28/2006 12:14 AM
    Gravatar
    how can i start application with another one I mean when I open one applicaiton, another one will automatically start related to the first one. How can I implement this
  30. Plucas 11/28/2006 12:44 PM
    Gravatar
    Here it is the VB.NET version ...

    Private Function HeyYeah() As Boolean
    Dim proc As Process = Process.GetCurrentProcess()
    Dim procs As Process() = Process.GetProcessesByName(proc.ProcessName)


    If procs.Length > 0 Then
    For Each p As Process In procs
    If (p.Id <> proc.Id) Then
    Try
    SendMessage(p.MainWindowHandle, cKeyMessage, IntPtr.Zero, IntPtr.Zero)
    Catch ex As Exception
    'MessageBox.Show("I couln't send a Windows Message to " + proc.ProcessName + " with PID ", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
    End Try
    End If
    Next
    End If
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Private Shared Function SendMessage(ByVal hwnd As IntPtr, <MarshalAs(UnmanagedType.U4)> ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
    End Function

    Protected Overrides Sub WndProc(ByRef message As Message)
    If (message.Msg = cKeyMessage) Then
    Trace.WriteLine("Hey hey hey")
    sbpLogin.Text = "hey hey hey"
    'Do what you need
    End If
    MyBase.WndProc(message)
    End Sub
  31. Shyam 1/18/2007 1:13 PM
    Gravatar
    Hi

    I just need to pass a string from App1 to App2. I am able to establish the link between them. I tried a postmessage from App1 to App2 and it works fine. But when I need to pass a string (say a link) I am struggling to get it. I would really appreciate if you can provide some sample code for the same for both App1 and App2.

    Thanks in Advance ...

    Shyam
  32. patriot 5/27/2007 6:06 AM
    Gravatar
    Great post. I was just looking for something similar. Thanks a lot!!!
  33. patriot 5/27/2007 6:18 AM
    Gravatar
    Great post. I was just looking for something similar when I came across this site.
  34. Crackman 6/10/2007 3:22 AM
    Gravatar
    >> I just need to pass a string from App1 to App2. I am able to establish the link between them.

    When sending WM_SETTEXT message from App1 and receiving it in App2 the lParam can be used for correct string sending. However you'll also need to make a difference between the message from App1 and other WM_SETTEXT messages.
  35. Amir Shahroudy 6/11/2007 2:48 AM
    Gravatar
    Thank You ...
    That was really usefull.
  36. Nilu 6/22/2007 4:28 AM
    Gravatar
    Hello.

    Amazing.

    CAn you please tell us how to do this by other way?
    Thank you
  37. subbu 10/4/2007 3:41 AM
    Gravatar
    This is great and this example works fine..

    But I need little more than this, I need to send message to an application that is iconized in the Tray.. buy the MainWindowHandle returns 0 and the message is not reaching..

    I tried with sample notepad.exe and still i I get MainWindowHandle as 0.

    Please advise.
  38. Drago 11/8/2007 2:45 AM
    Gravatar
    Thank you, your example works fine.

    I'm experiencing some problems on getting the messages, when I click on a menu item (App1) and leave the mouse pointer there - then I get no messages from App2. Somehow the main window on App1 is not responding for new Msgs anymore.

    Can somebody give a hint or help:)

    Thank you
  39. Adek 1/6/2008 5:44 PM
    Gravatar
    Thank you very much. This is very useful for me.
  40. Jasanite 1/14/2008 1:12 AM
    Gravatar
    Hi, just passed by and while solving my part i copy & pasted following code together that works for c#:

    private const int WM_COPYDATA = 0x4A;

    [StructLayout(LayoutKind.Sequential)]
    struct COPYDATASTRUCT
    {
    public int dwData;
    public int cbData;
    public int lpData;
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern int SendMessage(IntPtr hwnd, int wMsg, int
    wParam, ref COPYDATASTRUCT lParam);

    public void Send(string message)
    {
    COPYDATASTRUCT cds;
    cds.dwData = 0;
    cds.lpData = (int)Marshal.StringToHGlobalAnsi(message);
    cds.cbData = message.Length;

    Process currentProcess = Process.GetCurrentProcess();
    Process[] processCollection = Process.GetProcessesByName (currentProcess.ProcessName);
    foreach (Process p in processCollection)
    {
    if (p.Id != currentProcess.Id)
    {
    SendMessage(p.MainWindowHandle, (int)WM_COPYDATA, 0, ref cds);
    }
    }
    }

    protected override void WndProc(ref Message m)
    {
    switch (m.Msg)
    {
    case WM_COPYDATA:
    COPYDATASTRUCT CD =
    (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
    byte[] B = new byte[CD.cbData];
    IntPtr lpData = new IntPtr(CD.lpData);
    Marshal.Copy(lpData, B, 0, CD.cbData);
    string strData = Encoding.Default.GetString(B);
    break;

    default:
    base.WndProc(ref m);
    break;
    }
    }
  41. Jim 1/23/2008 3:22 PM
    Gravatar
    Any ideas how to accomplish this in WPF 3.5? WPF doesn't seem to support wndproc like a win forms app.
    thanks,
    jim
  42. Message pump stops working 3/14/2008 2:59 AM
    Gravatar
    I've implemented an ActiveX control to send a message from a browser to a Windows application similar to the WM_COPYDATA example above.
    All is fine until I try to hide the main window and then the WndProc doesn't seem to accept any messages. To get round this I have to make the Window Opacity=0. I also setting ShowInTaskbar=false causes the msg pump to stop working.

    The reason for hiding and ShowInTaskbar=false is because I have a balloon tip (notification window) working in the background.

    Any ideas?

    Also in the WM_COPYDATA example I think you should free the global shared memory after the for loop.

    paul
  43. bhavin 4/11/2008 5:00 AM
    Gravatar
    hi
    this help me a lot.
    can any explain me or guide me that how to receive messages from other famous application like outlook and web browser?

    where i can find that which messages are send by outlook or other famous application so that i can use them in my application.
  44. Eman 6/20/2008 10:39 AM
    Gravatar
    i need ur help to send a file between two different windows applications both using C#
  45. tk 11/7/2008 7:08 AM
    Gravatar
    How can we do communication between a windows service and a console application? Its seems your code work for winforms only. Please suggest some code.
  46. Djiki 12/5/2008 11:55 AM
    Gravatar
    Hi,

    Very useful article.

    Thanks Ryan
  47. Anish 1/5/2009 3:43 AM
    Gravatar
    Hi Ryan,

    I am a newbie to WIN API programming. I got a situation. I have an application which is written in delphi and c++. I only have the executable of that application.

    My need is to create an application that could communicate with this delphi application. Say, If I entered something in the textbox of my application and hit a button in my application, it should appear in the textbox in the delphi application.

    I hope you got the situation. Is there any way?

    Thanks in advance
    Anish
  48. 1/20/2009 7:53 AM
    Gravatar
    Programm aktivieren und Datei laden | hilpers
  49. Behtash Moradi 4/13/2009 12:51 AM
    Gravatar
    It is very helpful article, we also changed it to send data between 2 applications by using PostMessage API.


    Thank you in advance
    BEHTASH MORADI
  50. Silverio 11/13/2009 12:47 PM
    Gravatar
    Thank you very munch, this topic helped me a lot to do what I need in my application. Do you have a way to capture the execute process event from windows, I do need to check when an application is executed in the OS, to capture that event and to filter for an specific application. Thanks!
  51. Mrugesh Patel 3/30/2010 9:54 PM
    Gravatar
    how to access application menu using the application of vb.net?
    I am trying get menu using the sendmessage() as well as postmessage() but i am not success.
    please help me
  52. m_thakur 6/27/2010 11:19 PM
    Gravatar
    I am trying the same to send message from a window service to application running on current user desktop but its not working any clue, thank you so much.
  53. Gurumoorthy R. 8/10/2010 10:32 AM
    Gravatar
    i want to send data input regularly from my VB 6.0 Application to a third party Application both in my computer.data type are strings of XMl.Can i use your above codes for that purpose.can u provide any addl.codes if reqd.is it possible that the data can be assigned to the parameters?i am a novice to win32 api.Thanks in advance.
  54. 8/7/2012 3:59 AM
    Gravatar
    C# Adding JumplIsts to your C# Application (Can Of Code)
  55. 9/11/2014 4:21 AM
    Gravatar
    Communication between vb.net applications - Ziada Gyan
Comments have been closed on this topic.



 

News


Also see my CRM Developer blog

Connect:   @ryanfarley@mastodon.social

         

Sponsor

Sections