C++应用程序 xxx.cpp:
#include "framework.h" //必须的头文件在消息循环中, WM_CREATE 消息中进行加载和调用,因为我们的DLL需要当前窗口句柄作为参数,所以这里也需要传递这个参数 hWnd
需要添加 WM_COPYDATA 消息判断,因为在dll中是通过窗口句柄和 WM_COPYDATA 消息进行数据传递的
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ switch (message) { case WM_CREATE: { HMODULE hDll = LoadLibrary(L"get_computer_message.dll"); if (hDll) { typedef BOOL(*START_MONITOR)(HWND); START_MONITOR StartMonitor = (START_MONITOR)GetProcAddress(hDll, "StartMonitoring"); if (StartMonitor) { StartMonitor(hWnd); //句柄不能是 HWND hMainWnd = GetForegroundWindow(); 直接使用传递过来的 hWnd } } eventLogs.push_back(L"text"); SendMessageW(g_hList, LB_ADDSTRING, 0, (LPARAM)L"text2"); } break; case WM_COPYDATA: { PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam; if (pcds->dwData == EVENT_SYSTEM_FOREGROUND) { LPCWSTR text = (LPCWSTR)pcds->lpData; eventLogs.push_back(text); wchar_t debugMsg[512]; swprintf(debugMsg, _countof(debugMsg), L"Received event: 0x%X, Data: %s", pcds->dwData, (wchar_t*)pcds->lpData); OutputDebugStringW(debugMsg); SendMessageW(g_hList, LB_ADDSTRING, 0, (LPARAM)text); ScrollListBoxToBottom(g_hList); //滚动列表到底部 } return TRUE; } case WM_COMMAND: { break; case WM_PAINT: break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0;}
在VB中调用dll比较复杂,但也比较简单,需要先进行dll定义
需要在
Public Class Form1
类中进行如下定义:
StartMonitorDelegate 委托调用
LoadLibrary 加载dll
GetProcAddress 获取dll中方法地址
GetModuleFileName 获取模块名称
FreeLibrary 释放dll
' 声明与DLL函数匹配的委托(显式指定调用约定)
<UnmanagedFunctionPointer(CallingConvention.StdCall)>
Private Delegate Function StartMonitorDelegate(ByVal hWnd As IntPtr) As Boolean
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode)>
Private Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr
End Function
<DllImport("kernel32.dll")>
Private Shared Function GetProcAddress(ByVal hModule As IntPtr, ByVal lpProcName As String) As IntPtr
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode)>
Private Shared Function GetModuleFileName(ByVal hModule As IntPtr, ByVal lpFilename As StringBuilder, ByVal nSize As Integer) As Integer
End Function
<DllImport("kernel32.dll")>
Private Shared Function FreeLibrary(ByVal hModule As IntPtr) As Boolean
End Function
在
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
中进行dll加载
Dim hDll As IntPtr = LoadLibrary("get_computer_message.dll")
If hDll <> IntPtr.Zero Then
Dim procAddress As IntPtr = GetProcAddress(hDll, "StartMonitoring")
' 将指针转换为委托
Dim StartMonitor As StartMonitorDelegate =
CType(Marshal.GetDelegateForFunctionPointer(procAddress, GetType(StartMonitorDelegate)),
StartMonitorDelegate)
' 调用DLL函数 传入窗口句柄
Dim result As Boolean = StartMonitor(Me.Handle)
If result Then
TextBox1.AppendText("事件钩子DLL加载并启动成功!" & Environment.NewLine)
' 获取DLL路径
Dim dllPath As New StringBuilder(260)
GetModuleFileName(hDll, dllPath, dllPath.Capacity)
TextBox1.AppendText("加载DLL成功!路径: " & dllPath.ToString() & Environment.NewLine)
TextBox1.AppendText("函数地址: " & procAddress.ToInt64() & Environment.NewLine)
Else
TextBox1.AppendText("事件钩子DLL加载成功但启动失败!" & Environment.NewLine)
End If
Else
MessageBox.Show("加载DLL失败!")
End If
在消息循环中进行数据处理:
Dim textResult = Await SendTextToServer("电脑," & data) 方法需要进行网络请求,所以这里使用异步任务进行处理
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WM_COPYDATA Then '获取来自DLL的消息 这里获取所有的事件消息,所以这里要处理WM_COPYDATA消息
'处理来自DLL的消息
Dim cds As COPYDATASTRUCT = Marshal.PtrToStructure(Of COPYDATASTRUCT)(m.LParam)
If cds.dwData.ToInt32() = EVENT_SYSTEM_FOREGROUND Then
Dim data As String = Marshal.PtrToStringAuto(cds.lpData)
TextBox1.AppendText("获取到电脑事件: " & data & Environment.NewLine)
' 发送文本信息到服务器
' 启动异步任务
' 启动异步任务处理
Task.Run(Async Function()
Try
Dim textResult = Await SendTextToServer("电脑," & data)
Me.Invoke(Sub()
TextBox1.AppendText("本地服务数据保存状态: " & textResult & Environment.NewLine)
End Sub)
Catch ex As Exception
Me.Invoke(Sub()
TextBox1.AppendText("发送失败: " & ex.Message & Environment.NewLine)
End Sub)
End Try
End Function)
End If
End If
MyBase.WndProc(m) '必须调用 MyBase.WndProc 以保证消息链正常传递
End Sub