I am new to C# and IPC, trying to make an app that is single instance and when another process tries to start it wake up already running app instance and pass the args
to it. Everything is working according to my needs. But one problem is that I don't know how to set destination handle in program.cs
so it only sends the message to the destination app. currently it is broadcasting global and another software (miniget) which also listens to HWND_BROADCAST
receive it and wakeup as well. My already running instance is also listens to it. I want to set target handle for (IntPtr)NativeMethods.HWND_BROADCAST
static Mutex mutex = new Mutex(true, "mutex-unique-string-id");
[STAThread]
static void Main(string[] args)
{
if (mutex.WaitOne(TimeSpan.Zero, true))
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (args.Length == 0)
{
Application.Run(new MainForm(null));
}
else
{
Application.Run(new MainForm(args[0]));
}
mutex.ReleaseMutex();
}
else
{
if (args.Length == 0)
{
SendMessageClass.SendMessageWithDataUsingHGlobal((IntPtr)NativeMethods.HWND_BROADCAST, "", IntPtr.Zero);
}
else
{
SendMessageClass.SendMessageWithDataUsingHGlobal((IntPtr)NativeMethods.HWND_BROADCAST, args[0], IntPtr.Zero);
}
}
}
SendMessageClass
public class SendMessageClass
{
[System.Runtime.InteropServices.DllImport("user32.dll",CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(System.IntPtr hwnd, int msg,
IntPtr wparam, IntPtr lparam);
const int WM_COPYDATA = 0x4A;
const int WM_CLOSE = 0x0010;
public static void SendMessageWithDataUsingHGlobal(IntPtr destHandle, string str, IntPtr srcHandle)
{
COPYDATASTRUCT cds;
cds.dwData = srcHandle;
str = str + '\0';
cds.cbData = str.Length + 1;
cds.lpData = Marshal.AllocHGlobal(str.Length);
cds.lpData = Marshal.StringToHGlobalAnsi(str);
IntPtr iPtr = Marshal.AllocHGlobal(Marshal.SizeOf(cds));
Marshal.StructureToPtr(cds, iPtr, true);
// send to the MFC app
SendMessage(destHandle, WM_COPYDATA, srcHandle, iPtr);
// Don't forget to free the allocatted memory
Marshal.FreeCoTaskMem(cds.lpData);
Marshal.FreeCoTaskMem(iPtr);
}
}
WndProc
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
// program receives WM_COPYDATA Message from target app
case WM_COPYDATA:
if (m.Msg == WM_COPYDATA)
{
// get the data
COPYDATASTRUCT cds = new COPYDATASTRUCT();
cds = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
if (cds.cbData > 0)
{
byte[] data = new byte[cds.cbData];
Marshal.Copy(cds.lpData, data, 0, cds.cbData);
Encoding unicodeStr = Encoding.ASCII;
MessageBox.Show(new string(unicodeStr.GetChars(data)), "Received");
}
}
break;
}
base.WndProc(ref m);
}