There are a number of ways to make inter-process communications on Windows platform, some of which are memory mapped files, mailslots, named pipes etc. But there is another way of doing inter-process communications. the WM_COPYDATA window message enables you to send data to other applications, the only requirement on the receiving applications is that the receiving application should have a thread running message pump, running message pump is the only way to process window messages. I've created a sample application on how to use this technique to send string messages between two Windows Forms applications.
I have two Windows Forms applications, one is called SenderApp which is responsible to send messages, it typically uses the Win32 SendMessage to send WM_COPYDATA messages to the receiving application called ReceiverApp, in the SendMessage method, you should specify lParam arugment a pointer to a COPYDATASTRUCT structure, COPYDATASTRUCT carries on the data you want to send to other applications.
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT{
/// <summary>
/// Specifies data to be passed to the receiving application.
/// </summary>
public Int32 dwData;
/// <summary>
/// Specifies the size, in bytes, of the data pointed to by the lpData member.
/// </summary>
public Int32 cbData;
/// <summary>
/// Pointer to data to be passed to the receiving application. This member can be IntPtr.Zero.
/// </summary>
public IntPtr lpData;
}
[DllImport("user32.dll")]
public static extern Boolean SendMessage(IntPtr hwnd, UInt32 Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
Here is the code for the SenderApp:
public partial class SenderForm : Form
{
public const UInt32 WM_COPYDATA = 0x004a;
public SenderForm()
{
InitializeComponent();
}
private void sendButton_Click(Object sender, EventArgs e)
{
IntPtr receiverHwnd = FindWindow(null, "Receiver Form");
if (receiverHwnd == IntPtr.Zero)
{
MessageBox.Show("Receiver App hasn't start yet!");
return;
}
String msg = msgTextBox.Text;
// Allocate unmanaged memory.
IntPtr msgPtr = Marshal.AllocHGlobal(msg.Length);
// Convert string to a sequence of bytes.
Byte[] msgData = Encoding.Default.GetBytes(msg);
// Copy the bytes from managed heap to unmanaged memory.
Marshal.Copy(msgData, 0, msgPtr, msgData.Length);
COPYDATASTRUCT copyData = new COPYDATASTRUCT();
copyData.dwData = Encoding.Default.CodePage;
copyData.cbData = msgData.Length + 1; //We should take the null-terminator into consideration.
copyData.lpData = msgPtr;
SendMessage(receiverHwnd, WM_COPYDATA, this.Handle, ref copyData);
Marshal.FreeHGlobal(msgPtr);
}
/// <summary>
/// The main entry point for the SenderApp.
/// </summary>
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new SenderForm());
}
}
And this is code for ReceiverApp:
public partial class ReceiverForm : Form
{
public const UInt32 WM_COPYDATA = 0x004a;
public ReceiverForm()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_COPYDATA)
{
COPYDATASTRUCT copyData = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
Byte[] data = new Byte[copyData.cbData - 1]; //CLR doesn't recognize the null-terminator, so we should strip it.
Marshal.Copy(copyData.lpData, data, 0, data.Length);
String msg = Encoding.GetEncoding(copyData.dwData).GetString(data, 0, data.Length);
msgTextBox.Text = msg;
}
base.WndProc(ref m);
}
/// <summary>
/// The main entry point for the ReceiverApp.
/// </summary>
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ReceiverForm());
}
}
Put the above code up and running, you get the following screenshot:
You can download the full vs project from here.
2 comments:
This article was extremely interesting, especially since I was searching for thoughts on this subject last Thursday
Hello there! Incidentally, I like the way you have structured your site, it is super and very easy to follow. I have bookmarked you and will be back regularly. thanks for sharing my friend, it can make a great difference !
Post a Comment