在Windows下的两个进程之间通信通常有命名管道、消息队列、共享内存等实现方式,这篇文章要讲解的是使用Windows的API来实现简单的进程间通信。对于接收消息,只需要重写DefWndProc函数即可,对于发送消息,写一个发送消息MsgHandler来实现。

首先是MsgHandler类

using System;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;namespace CommunicationTest
{/// <summary>  /// 发送消息处理程序类/// 调用该方法“SendMessageToTargetWindow”发送  /// </summary>  class MsgHandler{/// <summary>  /// 系统定义的消息/// </summary>  private const int WM_COPYDATA = 0x004A;/// <summary>  /// 用户己定义消息/// </summary>  private const int WM_DATA_TRANSFER = 0x0437;// 使用Windows API的FindWindow方法[DllImport("User32.dll", EntryPoint = "FindWindow")]private static extern int FindWindow(string lpClassName, string lpWindowName);//使用Windows API的IsWindow方法[DllImport("User32.dll", EntryPoint = "IsWindow")]private static extern bool IsWindow(int hWnd);// 使用Windows API的SendMessage方法[DllImport("User32.dll", EntryPoint = "SendMessage")]private static extern int SendMessage(int hWnd,                 int Msg,                   int wParam,                ref COPYDATASTRUCT lParam   );// 使用Windows API的SendMessage方法[DllImport("User32.dll", EntryPoint = "SendMessage")]private static extern int SendMessage(int hWnd,                   int Msg,                   int wParam,                string lParam               );/// <summary>  /// CopyDataStruct  /// </summary>  private struct COPYDATASTRUCT{public IntPtr dwData;public int cbData;public IntPtr lpData;}/// <summary>  /// 向目标窗口发送消息/// </summary>  /// <param name="wndName">查找目标窗体名称</param>  /// <param name="msg">要发送的消息,字符串</param>  /// <returns>返回的数据是否成功或则失败</returns>  public static bool SendMessageToTargetWindow(string wndName, string msg){Debug.WriteLine(string.Format("SendMessageToTargetWindow: 向目标窗口发送消息 {0}: {1}", wndName, msg));int iHWnd = FindWindow(null, wndName);if (iHWnd == 0){string strError = string.Format("SendMessageToTargetWindow: 没有发现{0}窗体!", wndName);MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);Debug.WriteLine(strError);return false;}else{byte[] bytData = null;bytData = Encoding.Default.GetBytes(msg);COPYDATASTRUCT cdsBuffer;cdsBuffer.dwData = (IntPtr)100;cdsBuffer.cbData = bytData.Length;cdsBuffer.lpData = Marshal.AllocHGlobal(bytData.Length);Marshal.Copy(bytData, 0, cdsBuffer.lpData, bytData.Length);// 使用系统定义的消息wmcopydata来发送消息。 int iReturn = SendMessage(iHWnd, WM_COPYDATA, 0, ref cdsBuffer);if (iReturn < 0){string strError = string.Format("SendMessageToTargetWindow: 没有发现{0}窗体!", wndName);MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);Debug.WriteLine(strError);return false;}return true;}}/// <summary>  /// 向目标窗口发送消息/// </summary>  /// <param name="wndName">查找目标窗体名称</param>  /// <param name="wParam">first parameter, integer</param>  /// <param name="lParam">second parameter, string</param>  /// <returns>数据发送成或者失败</returns>  public static bool SendMessageToTargetWindow(string wndName, int wParam, string lParam){Debug.WriteLine(string.Format("SendMessageToTargetWindow: Send message to target window {0}: wParam:{1}, lParam:{2}", wndName, wParam, lParam));int iHWnd = FindWindow(null, wndName);if (iHWnd == 0){string strError = string.Format("SendMessageToTargetWindow: The target window [{0}] was not found!", wndName);MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);Debug.WriteLine(strError);return false;}else{//使用定义的消息wmdatatransfer来发送消息。int iReturn = SendMessage(iHWnd, WM_DATA_TRANSFER, wParam, lParam);if (iReturn < 0){string strError = string.Format("SendMessageToTargetWindow: Send message to the target window [{0}] failed!", wndName);MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);Debug.WriteLine(strError);return false;}return true;}}}
}

然后是数据接收窗体

using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;namespace CommunicationTest
{public partial class First : Form{/// <summary>  ///系统定义的消息/// </summary>  private const int WM_COPYDATA = 0x004A;/// <summary>  /// User defined message  /// </summary>  private const int WM_DATA_TRANSFER = 0x0437;/// <summary>  /// CopyDataStruct  /// </summary>  public struct COPYDATASTRUCT{public IntPtr dwData;public int cbData;public IntPtr lpData;}public First(){InitializeComponent();}/// <summary>  ///覆盖DefWndProc函数,以便通过它接收消息。 /// </summary>  /// <param name="m">message</param>  protected override void DefWndProc(ref System.Windows.Forms.Message m){switch (m.Msg){// 这里,我们使用wmcopydata消息来接收COPYDATASTRUCTcase WM_COPYDATA:COPYDATASTRUCT cds = new COPYDATASTRUCT();cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));byte[] bytData = new byte[cds.cbData];Marshal.Copy(cds.lpData, bytData, 0, bytData.Length);this.ProcessIncomingData(bytData);break;// 在这里,我们使用我们定义的消息wmdatatransfer来接收 // 普通数据,例如整数,字符串。// 我们尝试使用我们定义的消息来接收COPYDATASTRUCT,  // 但它没工作! !它告诉我们,我们试图进入受保护的   //,通常意味着其他记录被打破了。case WM_DATA_TRANSFER:int iWParam = (int)m.WParam;string sLParam = m.LParam.ToString();this.ProcessIncomingData(iWParam, sLParam);break;default:base.DefWndProc(ref m);break;}}/// <summary>  /// 处理传入的数据 /// </summary>  /// <param name="data">输入数据</param>  private void ProcessIncomingData(byte[] bytesData){string strRevMsg = "Receive message: " + Encoding.Default.GetString(bytesData);textBox7.Text = Encoding.Default.GetString(bytesData);//lstReceivedMsg.Items.Add(strRevMsg);}/// <summary>  /// 处理传入的数据  /// </summary>  /// <param name="iWParam">一个整数</param>  /// <param name="sLParam">一个字符串参数</param>  private void ProcessIncomingData(int iWParam, string sLParam){StringBuilder strBuilder = new StringBuilder();strBuilder.Append("wParam: ");strBuilder.Append(iWParam.ToString());strBuilder.Append(", lParam: ");strBuilder.Append(sLParam);//lstReceivedMsg.Items.Add(strBuilder.ToString());}private void FrmTest_Load(object sender, EventArgs e){this.Text = "First Test Form";this.txtCurrentWndName.Text = "First Test Form";this.txtTargetWndName.Text = "Second Test Form";}private void txtCurrentWndName_TextChanged(object sender, EventArgs e){this.Text = txtCurrentWndName.Text;}/// <summary>  /// 使用系统定义的消息wmcopydata向目标窗口发送消息/// </summary>  private void btnSend1_Click_1(object sender, EventArgs e){string strWndName = this.txtTargetWndName.Text;//检查目标窗口的名称为空/空if (string.IsNullOrEmpty(strWndName)){MessageBox.Show("目标窗口名不能为空或空", "Information", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);return;}string strMsg = this.txtSendingMsg.Text;// 检查发送消息是空的还是空的 if (string.IsNullOrEmpty(strMsg)){MessageBox.Show("发送消息必须不是空的或空的!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);return;}//向目标窗口发送消息bool bReturn = MsgHandler.SendMessageToTargetWindow(strWndName, strMsg);}/// <summary>/// 初始化页面/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Form1_Load(object sender, EventArgs e){this.Text = "First Test Form";this.txtCurrentWndName.Text = "First Test Form";this.txtTargetWndName.Text = "Second Test Form";}private void txtCurrentWndName_TextChanged_1(object sender, EventArgs e){this.Text = txtCurrentWndName.Text;}}
}

接收数据是只要重写DefWndProc函数

C#中实现两个程序的通信相关推荐

  1. 三菱伺服MR-JE-C与三菱FX-5UPLC进行两轴CCLINK-Basic总线通信程序

    三菱伺服MR-JE-C与三菱FX-5UPLC进行两轴CCLINK-Basic总线通信程序. 控制模式:有回原点,定位控制,速度控制,力矩控制,4种模式中随意切换. 赠送,:通信地址分配表,编程手册,威 ...

  2. java中形参不可以是对象吗_(重要)java都是值传递,与对象形参所指向的对象改变,其实参所指向的对象也相应改变并不矛盾(2011年9.30日一天写的两个程序的总结结果)...

    1.0建立二叉树的代码,在java中必须创建二叉树的方法必须用返回值,因为不存在c语言中的引用传递,在java中只有值传递 代码1为正确,代码2(没有使用返回值)为错误.那么为什么之前的例子中将对象作 ...

  3. Java黑皮书课后题第8章:*8.31(几何:交点)编写一个方法,返回两条直线的交点。四个点存放在4*2的二维数组points中。编写一个程序,提示用户输入4个点,并显示交点

    *8.31(几何:交点)编写一个方法,返回两条直线的交点.四个点存放在4*2的二维数组points中.编写一个程序,提示用户输入4个点,并显示交点 题目 题目描述 破题 代码 本题运行实例 题目 题目 ...

  4. Java黑皮书课后题第7章:*7.28(数学:组合)编写一个程序,提示用户输入10个整数,然后显示从这10个数中选出两个数的所有组合

    7.28(数学:组合) 题目 题目描述 破题 代码 运行示例 题目 题目描述 *7.28(数学:组合)编写一个程序,提示用户输入10个整数,然后显示从这10个数中选出两个数的所有组合 破题 声明一个长 ...

  5. Java黑皮书课后题第5章:*5.43(数学:组合)编写程序,显示从整数1到7中选择两个数字的所有组合,同时显示所有组合的总个数

    5.43(数学:组合)编写程序,显示从整数1到7中选择两个数字的所有组合,同时显示所有组合的总个数 题目 题目概述 破题 运行示例(要求) 代码 题目 题目概述 5.43(数学:组合)编写程序,显示从 ...

  6. 关于C#中实现两个应用程序消息通讯的问题

    最近项目中需要在两个应用程序之间通讯,这里的两个程序是在一台机器上,看了csdn上的一篇文章<如何在C#用WM_COPYDATA消息来实现两个进程之间传递数据>,原理是讲清楚了,但使起来很 ...

  7. 用户输入一个列表和两个整数作为下标,然后使用切片获取并输出列表中结余两个下标之间的元素组成的子列表。例如,用户输入 [1,2,3,4,5,6]和2,5,程序输出[3,4,5]。

    用户输入一个列表和两个整数作为下标,然后使用切片获取并输出列表中结余两个下标之间的元素组成的子列表.例如,用户输入 [1,2,3,4,5,6]和2,5,程序输出[3,4,5]. a = list(in ...

  8. 1.简述一个Activity跳转到另一个Activity时,两个Activity生命周期方法的执行过程。2.编写一个程序,要求在第一个界面中输入两个数字,在第二个界面显示第一个界面两个数字的和。

    1.简述一个Activity跳转到另一个Activity时,两个Activity生命周期方法的执行过程. 首先,我创建了一个MainActivity和SecondActivity两个Activity. ...

  9. matlab绘制两个函数,用matlab程序 在同一图中绘制两个函数,这两个函数分别是: , ,,matlab怎样同时画出两个函数图...

    导航:网站首页 > 用matlab程序 在同一图中绘制两个函数,这两个函数分别是: , ,,matlab怎样同时画出两个函数图 用matlab程序 在同一图中绘制两个函数,这两个函数分别是: , ...

最新文章

  1. 华为H3C ER3100由器限速方法合集
  2. hibernate一级缓存和二级缓存的区别[转]
  3. Perturbed Masking:和参数无关的预训练模型分析方法
  4. 文本分类和序列标注“深度”实践
  5. c++ 圆上任意点坐标计算_线性代数总结 第三章 向量代数与几何计算(空间平面和直线)...
  6. [BZOJ 2659] [Beijing wc2012] 算不出的算式
  7. 字符串%百分号 和 format 格式化
  8. 一道算法题:等价类思想在计数中的应用
  9. 如何在 Django REST Framework 中对分页结果过滤和排序?
  10. 复杂的三元转化为if() eles()
  11. 【金九银十】Java微服务面试题,看到你就是赚到
  12. 重磅!汇新云88会员节福利大放送
  13. iis部署网站java_值得分享的IIS部署网站详细步骤
  14. c语言lzma算法,在C中使用C-LZMA-SDK解压缩LZMA返回SZ_ERROR_DATA,因为输入流的第一个字节是!= 0...
  15. 技术驱动创新,带来的创业机遇
  16. 常用的分析管理工具方法【整理】
  17. 重塑科技燃料电池试验检测中心获CNAS认可评审,综合实力备受认可
  18. java软件工程师自我评价_Java开发工程师岗位自我评价怎么写
  19. 【信息奥赛题解】昆虫繁殖(详细分析题解 C++ 代码)
  20. Flutter Web(一)新建项目和登录页

热门文章

  1. 圆形上下挤压 matlab,基于Matlab的GUI设计双螺杆挤压机系统仿真软件
  2. 理解ES6——Promise
  3. 上线红包功能,真的真的没有你想的这么简单~
  4. windows程序设计(一)
  5. JS实现动态生成表格
  6. Jetson嵌入式系列模型部署-3
  7. smpl-x论文学习-部分翻译
  8. Windows - 百度网盘限速下载慢解决方案(官方提速方法)
  9. 全国计算机等级三级网络技术试卷详解(一)
  10. ShowWindow(SW_SHOWNORMAL)