64位进程和32位进程通信问题,接收端收不到 SendMessage发送的消息

 

最近在做一个项目的时候,采用了win32的SendMessage方法来发送数据,本来都没问题,后来增加了一个项目,必须采用的目标平台是x64的,没想到居然没办法通信了。

网上找了很久解决方案,整整尝试了一个周,终于解决了,居然是因为一个小小的参数类型引发的血案,所以记录下来,希望后面的同学别再跟我一样犯这样的错误啦!

 

参照以下3篇文章

https://blog.csdn.net/zaijzhgh/article/details/52171577

https://blog.csdn.net/xiaofeizai1116/article/details/54315895

https://www.cnblogs.com/mr-yoatl/p/7523835.html

原来是定义发送跟接收的结构体的一个类型定义的又问题,就是文中红色注释前面那句,之前定义的是int,现在改为IntPtr,就可以在32位和64位之间通信了

 

  1 public class Win32API
  2 {
  3 public const int WM_COPYDATA = 0X004A;//消息类型
  4 private const int WH_CALLWNDPROC = 4;    //钩子类型(监视SendMessage消息的传递)  
  5 public const int USER = 0X61;
  6 //以上为C#端发送,值得注意的就是:    
  7 //1>C#的结构体定义时要设置内存布局为顺序布局(即[StructLayout(LayoutKind.Sequential)])。    
  8 //2>如果结构体有字符串,记得要设置其大小(即[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)])。    
  9 //3>如果是C#端发送到C++端,记得把要发送的COPYDATASTRUCT 对象开辟一段“非托管内存”,然后赋值发送,因为C#内存机制为自动回收(就是系统帮你托  
 10 //管了,你不必担心内存泄漏问题),这样若果你不开辟直接发送的话,出了这个函数作用域,局部内存就会被回收,也就发送不到C++端了(你可以理解
 11 //为C++的局部变量的意思),因此要用Marshal.AllocHGlobal一份,赋值在发送,发送完记得释放掉
 12 //C#端钩子截获的消息的结构(对应WH_CALLWNDPROC)  
 13 //mbd 这个结构我找了好久,什么钩子对应什么结构  
 14 //网上只有监听鼠标啊,键盘啥的钩子结构,很少有监听SendMessage消息的钩子结构,为此度娘了一番,msdn了一番,  
 15 //找到钩子回调的原型函数ShellPro,然后几经周折发现CWPSTRUCT这个结构,看着有点儿眼熟,发现是上面那篇博客有提到过,  
 16 //于是再看了看,尼玛有点怪,于是在msdn该结构类型,加上[StructLayout(LayoutKind.Sequential)],    
 17 //转换C#类型,调试,然后终于是ok了
 18 //这里COPYDATASTRUCT对应C++的COPYDATASTRUCT,只不过是把它转为C#结构体  
 19 //注意结构体上面要加上[StructLayout(LayoutKind.Sequential)],表示结构体为顺序布局
 20 //启用非托管代码 
 21 [StructLayout(LayoutKind.Sequential)]
 22 public struct COPYDATASTRUCT
 23 {
 24 public IntPtr  dwData; //可以是任意值 ,必须是IntPtr类型,否则32位跟64位无法通信
 25 public int cbData; //长度  //指定lpData内存区域的字节数
 26 [MarshalAs(UnmanagedType.LPStr)]
 27 public string lpData; //发送给目录窗口所在进程的数据
 28 
 29 }
 30 
 31 [DllImport("User32.dll")]
 32 public static extern int SendMessage(
 33 IntPtr hWnd, // handle to destination window 
 34 int Msg, // message 
 35 IntPtr wParam, // first message parameter 
 36 ref COPYDATASTRUCT pcd // second message parameter 
 37 );
 38 
 39 [DllImport("User32.dll", EntryPoint = "FindWindow")]
 40 public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);//查找主目标窗体的运行句柄
 41 
 42 [DllImport("Kernel32.dll", EntryPoint = "GetConsoleWindow")]
 43 public static extern IntPtr GetConsoleWindow();
 44 
 45 private static class NativeMethods
 46 {
 47 internal const uint GW_OWNER = 4;
 48 
 49 internal delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
 50 
 51 [DllImport("User32.dll", CharSet = CharSet.Auto)]
 52 internal static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
 53 
 54 [DllImport("User32.dll", CharSet = CharSet.Auto)]
 55 internal static extern int GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
 56 
 57 [DllImport("User32.dll", CharSet = CharSet.Auto)]
 58 internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
 59 
 60 [DllImport("User32.dll", CharSet = CharSet.Auto)]
 61 internal static extern bool IsWindowVisible(IntPtr hWnd);
 62 }
 63 
 64 public static IntPtr GetMainWindowHandle(int processId)
 65 {
 66 IntPtr MainWindowHandle = IntPtr.Zero;
 67 
 68 NativeMethods.EnumWindows(new NativeMethods.EnumWindowsProc((hWnd, lParam) =>
 69 {
 70 IntPtr PID;
 71 NativeMethods.GetWindowThreadProcessId(hWnd, out PID);
 72 
 73 if (PID == lParam &&
 74 //NativeMethods.IsWindowVisible(hWnd) &&
 75 NativeMethods.GetWindow(hWnd, NativeMethods.GW_OWNER) == IntPtr.Zero)
 76 {
 77 MainWindowHandle = hWnd;
 78 return false;
 79 }
 80 
 81 return true;
 82 
 83 }), new IntPtr(processId));
 84 
 85 return MainWindowHandle;
 86 }
 87 
 88 /// <summary>
 89 /// 发送消息的方法
 90 /// </summary>
 91 /// <param name="message"></param>
 92 public static void SendMsg(string deviceName,string message)
 93 {
 94 string msg = deviceName + "^" + message;
 95 IntPtr maindHwnd = Win32API.FindWindow(null, "DDD窗体名称"); //获得主程序的句柄
 96 IntPtr hwndSendWindow = Process.GetCurrentProcess().Handle; //自己的进程句柄
 97 Win32API.COPYDATASTRUCT copydata = new Win32API.COPYDATASTRUCT();
 98 copydata.cbData = Encoding.Default.GetBytes(msg).Length+1; //长度 注意不要用strText.Length; 
 99 copydata.lpData = msg;//内容 
100 Win32API.SendMessage(maindHwnd, Win32API.WM_COPYDATA, hwndSendWindow, ref copydata);
101 }
102 
103 }
104 
105 
106 
107 
108 
109 
110 
111 接收消息的方法
112 
113 /// <summary>
114 /// 重写调用消息处理函数
115 /// </summary>
116 /// <param name="m">message消息</param>
117 protected override void WndProc(ref System.Windows.Forms.Message m)
118 {
119 try
120 {
121 switch (m.Msg)
122 {
123 case Win32API.WM_COPYDATA:
124 Win32API.COPYDATASTRUCT myStr = new Win32API.COPYDATASTRUCT();
125 Type myType = myStr.GetType();
126 myStr = (Win32API.COPYDATASTRUCT)m.GetLParam(myType); //m中获取LParam参数以myType类型的方式,让后转换问结构体。
127 string lpData = myStr.lpData;
128 var lpArr = lpData.Split('^'); //接收子驱动发送的消息,解析消息,lpArr[0]表示驱动名称,lpArr[1],表示接收的消息内容
129 if (lpArr.Length > 1)
130 {
131 WriteMsg(lpArr[0], lpData.Substring(lpData.IndexOf("^") + 1)); //将消息显示在右侧消息框中
132 }
133 break;
134 default:
135 // base.WndProc(ref m);s
136 break;
137 }
138 }
139 catch (Exception ex)
140 {
141 log4netHelp.Error(ex.Message);
142 }
143 
144 base.WndProc(ref m);
145 }

 

转载于:https://www.cnblogs.com/sharestone/p/9373492.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266512.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全国计算机等级考试题库二级C操作题100套(第23套)

第23套&#xff1a; 给定程序中&#xff0c;函数fun的功能是&#xff1a;找出NN矩阵中每列元素中的最大值&#xff0c;并按顺序依次存放于形参b所指的一维数组中。 请在程序的下划线处填入正确的内容并把下划线删除, 使程序得出正确的结果。 注意&#xff1a;源程序存放在考生…

html5 js

2019独角兽企业重金招聘Python工程师标准>>> http://labs.hyperandroid.com/mathmayhem 转载于:https://my.oschina.net/u/201125/blog/100934

初入职场的工作感悟

已经很久没有静下心来好好的做一次自我总结&#xff0c;个人博客已经搁浅数月&#xff0c;微信公众号也寥寥数篇。甚至我的GitHub 也将近半年没有点亮技能树了。难得的空闲时间&#xff0c;抓紧反思一下。 一个注重仪式感的我&#xff0c;在提前转正的那天&#xff0c;仅仅是发…

python按键盘上哪个键运行_python根据键盘输入进行相应操作

上篇文章介绍了如何利用pyhook模块监听鼠标键盘的事件&#xff0c;接下来如果需要通过监听的事件内容&#xff0c;来做对应的操作&#xff0c;需要对event的内容进行相应的判断。 如果仅仅通过event.key来进行判断&#xff0c;可以写成str(evnet.key) F12等&#xff0c;如果需…

全国计算机等级考试题库二级C操作题100套(第24套)

第24套&#xff1a; 程序通过定义学生结构体变量&#xff0c;存储了学生的学号、姓名和3门课的成绩。函数fun的功能是将形参a中的数据进行修改,把修改后的数据作为函数值返回主函数 进行输出。 例如&#xff1a;传给形参a的数据中&#xff0c;学号、姓名、和三门课的成绩依次是…

JavaCL 1.0.0-RC3 发布,性能大幅提升

JavaCL 发布 1.0 的第三个 RC 版本&#xff0c;该版本除了 bug 修复之外&#xff0c;性能方面有着非常大的提升&#xff0c;同时支持 OSGi 绑定。详情请看这里。 JavaCL 是一个封装了 OpenCL 图形API的 Java 类库&#xff0c;提供很多高级的图像处理功能。该项目的 JavaDoc 文档…

java 字符串数组定义_「string数组」string 数组怎么定义 - seo实验室

string数组string数组的定义有三种&#xff1a;String arr[] new String[10]; //创建一个长度为10的String 类型数组。String arr[] {"张三","李四"};String[] arr new String[10];相关阅读分析&#xff1a;如果直接输出未初始化的数组元素值&#xff0…

为什么空格拷贝到linux 会变成两个

为什么空格拷贝到linux 会变成两个 学习了&#xff1a;https://zhidao.baidu.com/question/266438357.html 在vi界面内输入:set paste 然后进行拷贝&#xff1b; 拷贝之后&#xff0c;输入:set nopaste 转载于:https://www.cnblogs.com/stono/p/9373893.html

python画图如何调整图例位置_Python-如何将图例排除在情节之外

小编典典 有很多方法可以做你想要的。要添加inalis和Navi所说的内容&#xff0c;可以使用bbox_to_anchor关键字参数将图例部分地放置在轴外and/or 减小字体大小。 在考虑减小字体大小&#xff08;这会使阅读起来非常困难&#xff09;之前&#xff0c;请尝试将图例放在不同的位置…

全国计算机等级考试题库二级C操作题100套(第25套)

第25套&#xff1a; 人员的记录由编号和出生年、月、日组成,N名人员的数据已在主函数中存入 结构体数组std中&#xff0c;且编号唯一。函数fun的功能是&#xff1a;找出指定编号人员的数据&#xff0c; 作为函数值返回,由主函数输出,若指定编号不存在&#xff0c;返回数据中的…

Haproxy 与 Cookie

1 什么是cookie ? 参考 cookie http://baike.baidu.com/view/835.htm Cookie&#xff0c;有时也用其复数形式Cookies&#xff0c;指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据&#xff08;通常经过加密&#xff09;。定义于RFC2109&#xff0…

java 动态按钮_java-向片段动态添加按钮

我一直在尝试向片段动态添加按钮,但是我尝试过的所有方法都不起作用.这些是我尝试过的一些方法&#xff1a;1.public View onCreateView(LayoutInflater inflater, Nullable ViewGroup container, Bundle savedInstanceState) {LinearLayout linearlayout new LinearLayout(ge…

进程线程区别,和线程初识

进程是计算机中最小的资源分配单位在利用多个CPU执行的过程中,对多个程序的资源进行管理和隔离进程的弊端开启和关闭 以及 切换 都会带来很大的时间开销过多的进程还会造成操作系统调度的压力线程线程是CPU调度的最小单位每个进程中至少有一个线程实际上执行代码的是线程线程属…

python绘制三维地形_【学习笔记】Python科学计算三维可视化(黄天羽、嵩天)(学习中。。)|python基础教程|python入门|python教程...

0 导学 目的&#xff1a;掌握利用三维效果表达科学和工程数据的能力 传播一种思想&#xff1a;可视化技术是数据之眼内容组织&#xff1a; 流体数据的标量可视化、矢量可视化实例 三维扫描数据&#xff08;模型/地形&#xff09;可视化实例 三维地球场景可视化实例 曲线UI交互控…

全国计算机等级考试题库二级C操作题100套(第26套)

第26套&#xff1a; 给定程序中已建立一个带有头结点的单向链表&#xff0c;链表中的各结点按数据域递增有序链接。函数fun的功能是&#xff1a;删除链表中数据域值相同的结点,使之只保留一个。 请在程序的下划线处填入正确的内容并把下划线删除&#xff0c;使程序得出正确的结…

在高科技产业当中,有时候你的产品出现了问题,你反过来可以把这个问题称为你的特点...

为什么80%的码农都做不了架构师&#xff1f;>>> 在高科技产业当中&#xff0c;有时候你的产品出现了问题&#xff0c;你反过来可以把这个问题称为你的特点。刚才讲的这种“大加小”的搭配就是属于这样的例子。by高通CEO保罗雅各布 看到这句话&#xff0c;深有感触…

python面向对象有什么用_Python 中的面向对象没有意义

许多人都在抨击面向对象&#xff0c;虽然我不认为他有什么问题&#xff0c;但我觉得至少在Python 中没必要。近来&#xff0c;许多人都在抨击面向对象&#xff0c;虽然我不认为面向对象本身有什么问题&#xff0c;但我觉得至少在 Python 中没这个必要。1、没有必要使用面向对象…

C# http请求

/// <summary> /// GET方式发送得结果 /// </summary> /// <param name"url">请求的url</param> public static string DoGetRequestSendData(string url) { HttpWebRequest hwRequest…

-9 逆序输出一个整数的各位数字_【每日算法】基础算法——归并排序[求逆序对的数量](四)(思想很经典)...

题目内容给定一个长度为n的整数数列&#xff0c;请你计算数列中的逆序对的数量。逆序对的定义如下&#xff1a;对于数列的第 i 个和第 j 个元素&#xff0c;如果满足 i < j 且 a[i] > a[j]&#xff0c;则其为一个逆序对&#xff1b;否则不是。输入格式第一行包含整数n&am…

全国计算机等级考试题库二级C操作题100套(第27套)

第27套&#xff1a; 给定程序中&#xff0c;函数fun的功能是&#xff1a;计算下式前n项的和作为函数值返回。 例如&#xff0c;当形参n的值为10时&#xff0c;函数返回&#xff1a;9.612558。 请在程序的下划线处填入正确的内容并把下划线删除,使程序得出正确的结果。 注意&am…