首页 > 代码库 > 利用COPYDATASTRUCT传递命令行参数给驻留内存的进程(SendMessage应用)

利用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 = http://www.mamicode.com/&H4A10   11 Private Declare Function FindWindow Lib "user32" Alias _12    "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName _13    As String) As Long14   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 Long18   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 COPYDATASTRUCT25     Dim ThWnd As Long26     Dim buf(1 To 255) As Byte27     Dim a As String, i As Long28   29      Get the hWnd of the target application30     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 ASCII33     Call CopyMemory(buf(1), ByVal a$, Len(a$))34     cds.dwData = http://www.mamicode.com/335     cds.cbData = http://www.mamicode.com/Len(a$) + 136     cds.lpData = http://www.mamicode.com/VarPtr(buf(1))37     i = SendMessage(ThWnd, WM_COPYDATA, Me.hwnd, cds)38 End Sub39   40 Private Sub Form_Load()41      This gives you visibility that the target app is running42      and you are pointing to the correct hWnd43     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 = http://www.mamicode.com/&H4A11 Global lpPrevWndProc As Long12 Global gHW As Long13  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 Long22  23 Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _24    (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As _25    Long) As Long26  27 Public Sub Hook()28     lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _29     AddressOf WindowProc)30     Debug.Print lpPrevWndProc31 End Sub32  33 Public Sub Unhook()34     Dim temp As Long35     temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)36 End Sub37  38 Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _39    ByVal wParam As Long, ByVal lParam As Long) As Long40     If uMsg = WM_COPYDATA Then41         Call mySub(lParam)42     End If43     WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)44 End Function45  46 Sub mySub(lParam As Long)47     Dim cds As COPYDATASTRUCT48     Dim buf(1 To 255) As Byte49     Dim a As String50  51     Call CopyMemory(cds, ByVal lParam, Len(cds))52  53     Select Case cds.dwData54      Case 155         Debug.Print "got a 1"56      Case 257         Debug.Print "got a 2"58      Case 359         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 Select64 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 Sub10   11 Private Sub Form_Unload(Cancel As Integer)12     Unhook13 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 CSMsgSender17 {18     /// <summary>19     /// MainWindow.xaml 的交互逻辑20     /// </summary>21     public partial class MainWindow : Window22     {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 = http://www.mamicode.com/3;38                 cdata.lpData =http://www.mamicode.com/ str;39                 cdata.cbData = http://www.mamicode.com/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 = http://www.mamicode.com/0x004A;50         public struct COPYDATASTRUCT51         {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 CSMsgReceiver12 {13     public partial class Form1 : Form14     {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 = http://www.mamicode.com/new COPYDATASTRUCT();27                     Type mytype = cdata.GetType();28                     cdata =http://www.mamicode.com/ (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 = http://www.mamicode.com/0x004A;39 40         //Windows在通过WM_COPYDATA消息传递期间,不提供继承同步方式。41         //其中,WM_COPYDATA对应的十六进制数为0x004A42         public struct COPYDATASTRUCT43         {44             public int dwData;45             public int cbData;46             [MarshalAs(UnmanagedType.LPStr)]47             public string lpData;48         }49     }50 }

 

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