近公司需要实现一个基于copydata进程间通信的功能。原来一直没有接触过Windows的进程通信,这次正好可以学习一下。
  程序是基于Winform的,下面直接上代码。
  公共类:
public class ImportFromDLL
{
public const int WM_COPYDATA = 0x004A;
//启用非托管代码
[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
public int dwData;    //not used
public int cbData;    //长度
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
[DllImport("User32.dll")]
public static extern int SendMessage(
IntPtr hWnd,     // handle to destination window
int Msg,         // message
IntPtr wParam,    // first message parameter
ref COPYDATASTRUCT pcd // second message parameter
);
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("Kernel32.dll", EntryPoint = "GetConsoleWindow")]
public static extern IntPtr GetConsoleWindow();
}
  发送方:
private void SendMessage()
{
//声明变量
string filepath = @"D:GetMsg.exe";//接收消息程序路径
string strText= "hello world!";//发送的消息//遍历系统中运行的进程,获取接收消息的进程
Process[] processes = Process.GetProcesses();
Process process = null;
foreach (Process p in processes)
{
try
{
//这两个进程的某些属性一旦访问抛出没有权限的异常
if (p.ProcessName != "System" && p.ProcessName != "Idle")
{
if (p.ProcessName == "GetMsg")
{
process = p;
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
//如果接收消息的进程未运行,则开启程序
if (process == null)
{//启动接收消息程序
process = System.Diagnostics.Process.Start(filepath);
Thread.Sleep(100);//等待接收消息的程序完全打开,否则消息不能发送成功。
}
//接收端的窗口句柄
IntPtr hwndRecvWindow = process.MainWindowHandle;
//自己的进程句柄
IntPtr hwndSendWindow = Process.GetCurrentProcess().Handle;
//填充COPYDATA结构
ImportFromDLL.COPYDATASTRUCT copydata = new ImportFromDLL.COPYDATASTRUCT();
copydata.cbData = Encoding.Default.GetBytes(strText).Length; //长度 注意不要用strText.Length;
copydata.lpData = strText;//内容
//发送消息
ImportFromDLL.SendMessage(hwndRecvWindow, ImportFromDLL.WM_COPYDATA, hwndSendWindow, ref copydata);
return;
}
  接收方:
protected override void WndProc(ref Message m)
{
if (m.Msg == ImportFromDLL.WM_COPYDATA)//根据Message.Msg区分消息类型,ImportFromDLL.WM_COPYDATA为发送方定义的消息类型
{
ImportFromDLL.COPYDATASTRUCT copyData = (ImportFromDLL.COPYDATASTRUCT)m.GetLParam(typeof(ImportFromDLL.COPYDATASTRUCT));//获取数据
MessageBox.Show(copyData.lpData);
}
base.WndProc(ref m);
}
  注:
  1、发送方和接收方均可以用C++、JAVA等实现,此处不再做讨论。
  2、在发送方。如果接收方未开启,打开接收方,在打开的同时,使用了:
  Thread.Sleep(100);//等待接收消息的程序打开,否则消息不能发送成功
  让程序等待。若不想让程序等待,由想传递消息给接收方,则可以考虑使用一下开启进程的重载方法:
  public static Process Start(string fileName, string arguments);
  public static Process Start(string fileName, string userName, SecureString password, string domain);
  public static Process Start(string fileName, string arguments, string userName, SecureString password, string domain);
  具体使用说明,可参照API文档。