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

来源:互联网 发布:大数据分析应用 编辑:程序博客网 时间:2024/06/05 02:18

我们知道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 = &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 1024) As Byte27     Dim a As String, i As Long, lLen 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     lLen = LenB(StrConv(a, vbFromUnicode))34     Call CopyMemory(buf(1), ByVal a, lLen)35     cds.dwData = 336     cds.cbData = lLen + 137     cds.lpData = VarPtr(buf(1))38     i = SendMessage(ThWnd, WM_COPYDATA, Me.hwnd, cds)39 End Sub40   41 Private Sub Form_Load()42     ' This gives you visibility that the target app is running43     ' and you are pointing to the correct hWnd44     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 = &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 1024) 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 = 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 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 = 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对应的十六进制数为0x004A42         public struct COPYDATASTRUCT43         {44             public int dwData;45             public int cbData;46             [MarshalAs(UnmanagedType.LPStr)]47             public string lpData;48         }49     }50 }


0 0