• 利用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 1024) 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(1), ByVal a, lLen)
    35     cds.dwData = 3
    36     cds.cbData = lLen + 1
    37     cds.lpData = VarPtr(buf(1))
    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 = (-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 1024) 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 }
  • 相关阅读:
    disable_irq与disable_irq_nosync使用场景
    linux中断处理原理分析
    工作队列(workqueue) create_workqueue/schedule_work/queue_work
    使用git建立远程仓库,让别人git clone下来
    C中字符串的几种定义方法及说明
    Linux 2.6内核Makefile浅析
    探究platform_driver中的shutdown用途
    匆匆
    至强CPU性能排行,从X3210起,由低至高排列。
    Linux 命令行快捷键
  • 原文地址:https://www.cnblogs.com/chriskwok/p/4159768.html
Copyright © 2020-2023  润新知