利用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 }

 

你可能感兴趣的:(message)