我们知道Window进程之间通过API的SendMessage方法传递消息。但是方法参数lParam是Long型,那么如果传递一个字符串(譬如命令行参数)应该怎么办呢,甚至一个对象、结构呢。VB的发送接收需要通过传递指针实现(换言之是字符串的内存地址),下面总结VB方式、C#方式各自如何实现消息的发送与接收;各自是可以互换的,譬如C#发送的消息,VB窗口可以收到;相反亦可以。当然同种语言之间更加没问题了。

VB发送端 Form1.frm:

  1. Option Explicit
  2.  
  3. Private Type COPYDATASTRUCT
  4. dwData As Long
  5. cbData As Long
  6. lpData As Long
  7. End Type
  8.  
  9. Private Const WM_COPYDATA = &H4A
  10.  
  11. Private Declare Function FindWindow Lib "user32" Alias _
  12. "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName _
  13. As String) As Long
  14.  
  15. Private Declare Function SendMessage Lib "user32" Alias _
  16. "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal _
  17. wParam As Long, lParam As Any) As Long
  18.  
  19. 'Copies a block of memory from one location to another.
  20. Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
  21. (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
  22.  
  23. Private Sub Command1_Click()
  24. Dim cds As COPYDATASTRUCT
  25. Dim ThWnd As Long
  26. Dim buf( To ) As Byte
  27. Dim a As String, i As Long, lLen As Long
  28.  
  29. ' Get the hWnd of the target application
  30. ThWnd = FindWindow(vbNullString, "Target")
  31. a$ = "It Works on " & Format(Now, "yyyy-MM-dd HH:mm:ss") & " !"
  32. ' Copy the string into a byte array, converting it to ASCII
  33. lLen = LenB(StrConv(a, vbFromUnicode))
  34. Call CopyMemory(buf(), ByVal a, lLen)
  35. cds.dwData =
  36. cds.cbData = lLen +
  37. cds.lpData = VarPtr(buf())
  38. i = SendMessage(ThWnd, WM_COPYDATA, Me.hwnd, cds)
  39. End Sub
  40.  
  41. Private Sub Form_Load()
  42. ' This gives you visibility that the target app is running
  43. ' and you are pointing to the correct hWnd
  44. Me.Caption = Hex$(FindWindow(vbNullString, "Target"))
  45. End Sub

VB接收端

1。MsgHook.bas:

  1. Option Explicit
  2.  
  3. Type COPYDATASTRUCT
  4. dwData As Long
  5. cbData As Long
  6. lpData As Long
  7. End Type
  8.  
  9. Public Const GWL_WNDPROC = (-)
  10. Public Const WM_COPYDATA = &H4A
  11. Global lpPrevWndProc As Long
  12. Global gHW As Long
  13.  
  14. 'Copies a block of memory from one location to another.
  15. Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
  16. (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
  17.  
  18. Declare Function CallWindowProc Lib "user32" Alias _
  19. "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As _
  20. Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As _
  21. Long) As Long
  22.  
  23. Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
  24. (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As _
  25. Long) As Long
  26.  
  27. Public Sub Hook()
  28. lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
  29. AddressOf WindowProc)
  30. Debug.Print lpPrevWndProc
  31. End Sub
  32.  
  33. Public Sub Unhook()
  34. Dim temp As Long
  35. temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
  36. End Sub
  37.  
  38. Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _
  39. ByVal wParam As Long, ByVal lParam As Long) As Long
  40. If uMsg = WM_COPYDATA Then
  41. Call mySub(lParam)
  42. End If
  43. WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
  44. End Function
  45.  
  46. Sub mySub(lParam As Long)
  47. Dim cds As COPYDATASTRUCT
  48. Dim buf( To ) As Byte
  49. Dim a As String
  50.  
  51. Call CopyMemory(cds, ByVal lParam, Len(cds))
  52.  
  53. Select Case cds.dwData
  54. Case
  55. Debug.Print "got a 1"
  56. Case
  57. Debug.Print "got a 2"
  58. Case
  59. Call CopyMemory(buf(), ByVal cds.lpData, cds.cbData)
  60. a$ = StrConv(buf, vbUnicode)
  61. a$ = Left$(a$, InStr(, a$, Chr$()) - )
  62. Form1.Label1.Caption = a$
  63. End Select
  64. End Sub

2。Target.frm:

  1. Option Explicit
  2.  
  3. Private Sub Form_Load()
  4. gHW = Me.hwnd
  5. Hook
  6. Me.Caption = "Target"
  7. Me.Show
  8. Label1.Caption = Hex$(gHW)
  9. End Sub
  10.  
  11. Private Sub Form_Unload(Cancel As Integer)
  12. Unhook
  13. End Sub

C#的发送端:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Data;
  8. using System.Windows.Documents;
  9. using System.Windows.Input;
  10. using System.Windows.Media;
  11. using System.Windows.Media.Imaging;
  12. using System.Windows.Navigation;
  13. using System.Windows.Shapes;
  14. using System.Runtime.InteropServices;
  15.  
  16. namespace CSMsgSender
  17. {
  18. /// <summary>
  19. /// MainWindow.xaml 的交互逻辑
  20. /// </summary>
  21. public partial class MainWindow : Window
  22. {
  23. public MainWindow()
  24. {
  25. InitializeComponent();
  26. }
  27.  
  28. private void button1_Click(object sender, RoutedEventArgs e)
  29. {
  30. int hwnd = FindWindow(null, "Target");
  31. if (hwnd != )
  32. {
  33. string str = "It Works on " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " !";
  34. byte[] arr = System.Text.Encoding.Default.GetBytes(str);
  35. int len = arr.Length;
  36. COPYDATASTRUCT cdata;
  37. cdata.dwData = ;
  38. cdata.lpData = str;
  39. cdata.cbData = len + ;
  40. SendMessage(hwnd, WM_COPYDATA, , ref cdata);
  41. }
  42. }
  43.  
  44. [DllImport("User32.dll")]
  45. public static extern int SendMessage(int hwnd, int msg, int wParam, ref COPYDATASTRUCT lParam);
  46. [DllImport("User32.dll")]
  47. public static extern int FindWindow(string lpClassName, string lpWindowName);
  48.  
  49. private const int WM_COPYDATA = 0x004A;
  50. public struct COPYDATASTRUCT
  51. {
  52. public int dwData;
  53. public int cbData;
  54. [MarshalAs(UnmanagedType.LPStr)]
  55. public string lpData;
  56. }
  57. }
  58. }

C#接收端:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.Runtime.InteropServices;
  10.  
  11. namespace CSMsgReceiver
  12. {
  13. public partial class Form1 : Form
  14. {
  15. public Form1()
  16. {
  17. InitializeComponent();
  18. this.Text = "Target";
  19. }
  20.  
  21. protected override void DefWndProc(ref Message m)
  22. {
  23. switch (m.Msg)
  24. {
  25. case WM_COPYDATA:
  26. COPYDATASTRUCT cdata = new COPYDATASTRUCT();
  27. Type mytype = cdata.GetType();
  28. cdata = (COPYDATASTRUCT)m.GetLParam(mytype);
  29. this.textBox1.Text = cdata.lpData;
  30. break;
  31. default:
  32. base.DefWndProc(ref m);
  33. break;
  34. }
  35. }
  36.  
  37. //WM_COPYDATA消息的主要目的是允许在进程间传递只读数据。
  38. private const int WM_COPYDATA = 0x004A;
  39.  
  40. //Windows在通过WM_COPYDATA消息传递期间,不提供继承同步方式。
  41. //其中,WM_COPYDATA对应的十六进制数为0x004A
  42. public struct COPYDATASTRUCT
  43. {
  44. public int dwData;
  45. public int cbData;
  46. [MarshalAs(UnmanagedType.LPStr)]
  47. public string lpData;
  48. }
  49. }
  50. }

利用COPYDATASTRUCT传递命令行参数给驻留内存的进程(SendMessage应用)的更多相关文章

  1. 传递命令行参数示例代码 (C 和 Python)

    C语言 在 C 语言中, 使用 main 函数的输入参数 argc 和 argv 传入命令行参数. argc 为 int 类型, 表示传入命令行参数的个数 (argument count); argv ...

  2. .NET Core采用的全新配置系统[5]: 聊聊默认支持的各种配置源[内存变量,环境变量和命令行参数]

    较之传统通过App.config和Web.config这两个XML文件承载的配置系统,.NET Core采用的这个全新的配置模型的最大一个优势就是针对多种不同配置源的支持.我们可以将内存变量.命令行参 ...

  3. [Objective-C语言教程]命令行参数(23)

    执行时,可以将一些值从命令行传递给Objective-C程序. 这些值称为命令行参数,很多时候它们对程序很重要,特别是当想要从外部控制程序而不是在代码中对这些值进行硬编码时就很有用了. 命令行参数使用 ...

  4. 命令行参数(argc, argv)

    每个C语言程序都必须有一个称为main()的函数,作为程序启动的起点.当执行程序时,命令行参数(command-line argument)(由shell逐一解析)通过两个入参提供给main()函数. ...

  5. C# 动态生成word文档 [C#学习笔记3]关于Main(string[ ] args)中args命令行参数 实现DataTables搜索框查询结果高亮显示 二维码神器QRCoder Asp.net MVC 中 CodeFirst 开发模式实例

    C# 动态生成word文档 本文以一个简单的小例子,简述利用C#语言开发word表格相关的知识,仅供学习分享使用,如有不足之处,还请指正. 在工程中引用word的动态库 在项目中,点击项目名称右键-- ...

  6. Qt之命令行参数

    简述 在Qt之进程间通信(QProcess)一节,我们讲解了如何通过QProcess来进行进程间的通信.主要通过启动外部程序,然后通过命令行的方式传递参数. 这里,我们可以通过Qt Creator来设 ...

  7. 【NS-3学习】ns3-模拟基础:关键概念,日志,命令行参数

    前言 本篇博客先介绍在仿真过程中会使用到的一些关键概念,然后介绍便于调试仿真脚本的常用技术:日志.命令行参数. 关键概念 节点 在因特网术语中,主机(终端)是指任何一台连接到网络的计算设备.ns-3并 ...

  8. Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数

    特殊变量列表 变量 含义 $0 当前脚本的文件名 $n 传递给脚本或函数的参数.n 是一个数字,表示第几个参数.例如,第一个参数是$1,第二个参数是$2. $# 传递给脚本或函数的参数个数. $* 传 ...

  9. powershell脚本,命令行参数传值,并绑定变量的例子

    这是小技巧文章,所以文章不长.但原创唯一,非常重要.我搜了下,还真没有人发 powershell怎样 [命令行 参数 绑定],所以我决定写成博客. 搜索关键字如下: powershell 命令行 参数 ...

随机推荐

  1. socket异步编程--libevent的使用

    使用 libevent 和 libev 提高网络应用性能 http://www.ibm.com/developerworks/cn/aix/library/au-libev/ libevent实现ht ...

  2. 使用CSS3制作漂亮的按钮

    我给大家介绍一下如何使用CSS3来制作一个圆角阴影.渐变色的漂亮的按钮,它不需要任何图片和javascript脚本,只需要CSS3就可以轻松实现按钮效果,并且可以适用于任意HTML元素,想div,sp ...

  3. (转载)怎么写tab?

    演示地址:http://www.adanghome.com/js_demo/3/ =========================================================== ...

  4. linux 如何让程序后台执行

    $ (./test.sh &)   $ setsid ./test.sh &   $ nohup ./test.sh &   具体的转自:http://digdeeply.or ...

  5. android 点九PNG技术 适应不同分辨率 完美显示效果

    .9.png是一种非失真性压缩位图图形文件格式.PNG格式是非失真性压缩的,允许使用类似于GIF格式的调色板技术,支持真彩色图像,并具备阿尔法通道(半透明)等特性.现在有很多人使用PNG格式于互联网及 ...

  6. Centos环境下部署游戏服务器-SVN

    版本控制工具的文章已经被写滥了,所以本篇文章不想介绍如何安装Svn如何可视化操作这些东西.本篇文章讲述我自己对Svn的理解,以及在命令行下操作.为啥不应可视化界面?有两方面的原因,远程登录到服务器都是 ...

  7. 统计MySQL数据表大小

    SELECT CONCAT(TRUNCATE(SUM(data_length)/1024/1024,2),'MB') AS data_size,CONCAT(TRUNCATE(SUM(max_data ...

  8. Reads sequentially from multiple sources

    /* * Copyright (C) 2016 Stephen Ostermiller * http://ostermiller.org/contact.pl?regarding=Java+Utili ...

  9. c# ffmpeg常用参数

    c#  ffmpeg常用参数 转换文件格式的同时抓缩微图: ffmpeg -i "test.avi" -y -f image2 -ss 8 -t 0.001 -s 350x240 ...

  10. linux下c程序调用reboot函数实现直接重启【转】

    转自:http://www.blog.chinaunix.net/uid-20564848-id-73878.html linux下c程序调用reboot函数实现直接重启 当然你也可以直接调用syst ...