Reputation: 4193
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
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
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.
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
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
Reputation: 649
I frequently use MSMQ for this.
http://www.csharphelp.com/archives3/archive581.html
Upvotes: 2
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