利用COPYDATASTRUCT传递命令行参数给驻留内存的进程(SendMessage应用)

我们知道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(1 To 255) As Byte
27     Dim a As String, i 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     Call CopyMemory(buf(1), ByVal a$, Len(a$))
34     cds.dwData = 3
35     cds.cbData = Len(a$) + 1
36     cds.lpData = VarPtr(buf(1))
37     i = SendMessage(ThWnd, WM_COPYDATA, Me.hwnd, cds)
38 End Sub
39
40 Private Sub Form_Load()
41     ‘ This gives you visibility that the target app is running
42     ‘ and you are pointing to the correct hWnd
43     Me.Caption = Hex$(FindWindow(vbNullString, "Target"))
44 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 = (-4)
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(1 To 255) As Byte
49     Dim a As String
50
51     Call CopyMemory(cds, ByVal lParam, Len(cds))
52
53     Select Case cds.dwData
54      Case 1
55         Debug.Print "got a 1"
56      Case 2
57         Debug.Print "got a 2"
58      Case 3
59         Call CopyMemory(buf(1), ByVal cds.lpData, cds.cbData)
60         a$ = StrConv(buf, vbUnicode)
61         a$ = Left$(a$, InStr(1, a$, Chr$(0)) - 1)
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 != 0)
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 = 3;
38                 cdata.lpData = str;
39                 cdata.cbData = len + 1;
40                 SendMessage(hwnd, WM_COPYDATA, 10, 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 }
时间: 2024-10-19 05:01:05

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

在命令行上编译本机 C++ 程序以及传递命令行参数给主函数

1.首先,打开"开发人员命令提示" 2.创建一个新目录来保存你的程序. 在"开发人员命令提示"窗口中,输入 cd \ 命令,以将目录更改为驱动器根目录.(md:创建文件夹). 3.在命令提示处,输入 notepad hello.cpp(示例程序.) 4.在命令提示处,输入 cl /EHsc hello.cpp 来编译你的程序. cl.exe 编译器会生成包含已编译代码的 .obj 文件.然后运行链接器来创建名为 hello.exe 的可执行程序 5.若要运行 hel

向WinForm程序传递命令行参数以及让程序后台运行的

1 [STAThread] 2 static void Main(string[] args) 3 { 4 Application.EnableVisualStyles(); 5 Application.SetCompatibleTextRenderingDefault(false); 6 if (args.Length == 0) 7 Application.Run(new Form1()); 8 else 9 Application.Run(new Form1(args)); 10 } pu

聊聊默认支持的各种配置源[内存变量,环境变量和命令行参数]

聊聊默认支持的各种配置源[内存变量,环境变量和命令行参数] 较之传统通过App.config和Web.config这两个XML文件承载的配置系统,.NET Core采用的这个全新的配置模型的最大一个优势就是针对多种不同配置源的支持.我们可以将内存变量.命令行参数.环境变量和物理文件作为原始配置数据的来源,如果采用物理文件作为配置源,我们可以选择不同的格式(比如XML.JSON和INI等) .如果这些默认支持的配置源形式还不能满足你的需求,我们还可以通过注册自定义ConfigurationSour

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

较之传统通过App.config和Web.config这两个XML文件承载的配置系统,.NET Core采用的这个全新的配置模型的最大一个优势就是针对多种不同配置源的支持.我们可以将内存变量.命令行参数.环境变量和物理文件作为原始配置数据的来源,如果采用物理文件作为配置源,我们可以选择不同的格式(比如XML.JSON和INI等) .如果这些默认支持的配置源形式还不能满足你的需求,我们还可以通过注册自定义ConfigurationSource的方式将其他形式数据作为我们的配置来源. [ 本文已经同

通过命令行参数打开文件

这个就是命令行,它的作用是给windows传递指令的,传递命令行参数就是通过它去传递的.因为是通过命令行传递的,所以传递的参数最终的名字就叫做命令行参数. 原文地址:https://www.cnblogs.com/dabing0983/p/10584685.html

(三)、利用命令行参数输入多个参数,判断该数组是否为回文数组

1 /* 2 利用命令行参数输入多个参数,并赋值给一数组,同时判断该数组是否为回文数组 3 –PS:例如数组{“123”,”222”,”333”,”222”,”123”}就是回文数组,即元素倒置过后与原元素一样 4 */ 5 package com.gen; 6 public class ArgumentHuiwen { 7 public static void main(String args[]) 8 { 9 int num[]=new int[100]; 10 int len=args.l

(四)、利用命令行参数输入一个整数,打印空心菱形

1 /*利用命令行参数输入一个整数,并判断该数字是否为奇数,如果是奇数,则用其作行数打印空心菱形 2 –PS:将字符串转换为数字的方法 3 •int num=Integer.parseInt(String number);*/ 4 5 package com.gen; 6 public class ArgumentKongLing { 7 public static void main(String args[]) 8 { 9 for (int m= 0; m < args.length;m++

(五)、利用命令行参数输入三个整数,并对三个数字进行降序排列

1 /*利用命令行参数输入三个整数,并对三个数字进行降序排列. 2 –PS:将字符串转换为数字的方法 3 •int num=Integer.parseInt(String number);*/ 4 package com.gen; 5 6 public class ArgumentOrder { 7 public static void main(String args[]) 8 { 9 System.out.println("Please input three number by args:

命令行参数(argc, argv)

每个C语言程序都必须有一个称为main()的函数,作为程序启动的起点.当执行程序时,命令行参数(command-line argument)(由shell逐一解析)通过两个入参提供给main()函数.第一个参数int argc,表示命令行参数的个数.第二个参数char *argv[],是一个指向命令行参数的指针数组,每一参数又都是以空字符(null) 结尾的字符串.第一个字符串,亦即argv[0]指向的,(通常)是该程序的名称.argv中的指针列表以NULL指针结尾(即argv[argc]为NU