Samir
Samir

Reputation: 4193

Pass a message to another exe from an exe C#

I have two exe running, C# console programs. From one, I need to tell the second exe to do something? How can I do this? I looked at

(Remotable.CommonAssembly)Activator.GetObject(typeof(Remotable.CommonAssembly)

but from here I can call a method of the CommonAssembly(referenced dll) not the exe one's.

Upvotes: 4

Views: 10884

Answers (5)

Scott Michaels
Scott Michaels

Reputation:

This should do the trick for you...

[code]

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace TestApp
{
public static class Messenger
{
    public const uint WM_USER = 0x0400;

    public const int MyMessage = 0x00000001;;

    [DllImport("User32.dll")]
    private static extern int RegisterWindowMessage(string lpString);

    [DllImport("User32.dll", EntryPoint = "FindWindow")]
    internal static extern IntPtr FindWindow(String lpClassName, String lpWindowName);

    //For use with WM_COPYDATA and COPYDATASTRUCT
    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    internal static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

    //For use with WM_COPYDATA and COPYDATASTRUCT
    [DllImport("User32.dll", EntryPoint = "PostMessage")]
    internal static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    internal static extern uint SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, int lParam);

    [DllImport("User32.dll", EntryPoint = "PostMessage")]
    internal static extern int PostMessage(int hWnd, int Msg, int wParam, int lParam);

    [DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
    internal static extern bool SetForegroundWindow(int hWnd);


    //Used for WM_COPYDATA for string messages
    public struct COPYDATASTRUCT
    {
        public IntPtr dwData;
        public int cbData;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpData;
    }


    internal static int sendWindowsStringMessage(int hWnd, int wParam, string msg)
    {
        int result = 0;

        if (hWnd > 0)
        {
            byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);
            int len = sarr.Length;
            COPYDATASTRUCT cds;
            cds.dwData = (IntPtr)100;
            cds.lpData = msg;
            cds.cbData = len + 1;
            result = SendMessage(hWnd, (int)WM_USER, wParam, ref cds);
        }

        return result;
    }

    internal static uint sendWindowsMessage(IntPtr hWnd, uint Msg, IntPtr wParam, int lParam)
    {
        uint result = 0;

        if (hWnd != IntPtr.Zero)
        {
            result = SendMessage(hWnd, Msg, wParam, lParam);
        }

        return result;
    }

    internal static IntPtr getWindowId(string className, string windowName)
    {
        return FindWindow(className, windowName);
    }
}

}

In your calling method:

uint result = 0;
IntPtr hWnd = Messenger.getWindowId(null, "MyOtherApp-Window_Title");
result = Messenger.sendWindowsMessage(hWnd, Messenger.WM_USER, Handle, Messenger.MyMessage);

[/code]

Upvotes: 2

devdimi
devdimi

Reputation: 2462

For simple scenarios a plain old windows event would be enough - a program waits to be signaled to do something.

Spawn a thread in the waiting program that waits for the event.

//Program 1

EventWaitHandle evt = OpenOrCreateEvent("Global\\MyEvent");
evt.WaitOne(); // this thread will block waiting without wasting CPU cycles, 
               // it will be be signaled from the kernel 
               // when the event is set
DoStuff();


//Program 2

EventWaitHandle evt = OpenOrCreateEvent("Global\\MyEvent");
evt.Set();

Take a look at the EventWaitHandle, ManualResetEvent, AutoResetEvent classes.

  • Consider which program is going to create the event - you could try to open the event from both programs, if it doesn't exist than create it.
  • Prefix the event name with 'Global\' if one of the programs is a service ( and/or running in other session/user). Otherwise it won't work on Vista or later.
  • When creating the event you may need to set security attributes so it can be opened from other processes from other sessions.

Advanced IPC mechanisms like WCF, Remoting, DCOM, CORBA, etc may be better if you have more complicated communication protocol with different actions to trigger, return values and so on. For simple cases (a couple) of windows events would be enough.

Notice If you need to transfer data between your processes consider memory mapped files. "Official" .NET classes for them will be available with .NET 4.0, currently you can use http://github.com/tomasr/filemap/tree/master

Upvotes: 5

JP Alioto
JP Alioto

Reputation: 45117

You might consider IPC. NamedPipeClientStream and NamedPipeServerStream are pretty simple. Here's an example where IPC is used to pass command line arguments from one instance of an application to another. It's not exactly what you want to do, but pretty close.

Upvotes: 1

cookre
cookre

Reputation: 649

I frequently use MSMQ for this.

http://www.csharphelp.com/archives3/archive581.html

Upvotes: 2

Andy White
Andy White

Reputation: 88345

Look into WCF for inter-process communication in .NET. There are a variety of protocols available for same-machine or remote-machine communication. For same-machine, I would recommend checking out named pipes or the .NET TCP binding.

There is a slight learning curve for WCF, but there are plenty of tutorials out there, and it's something that's definitely worth learning.

Upvotes: 3

Related Questions