0%

模拟手动从桌面运行程序(1)

简介

有的时候做测试,需要模拟手动从桌面运行程序,来区分使用API运行程序的效果

工作原理

原理就是查找桌面窗口,遍历桌面窗口的所有项,找到并选择目标项,再发送按下回车键

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <windows.h>
#include <commctrl.h>
BOOL RunDesktopItem(PCWSTR pName)
{
if (!pName) return FALSE;
// 查找桌面窗口
HWND hWndParent = FindWindowW(L"Progman", L"Program Manager");
if (!hWndParent) return FALSE;
HWND hWndSHELLDLL_DefView = FindWindowExW(hWndParent, NULL, L"SHELLDLL_DefView", NULL);
if (!hWndSHELLDLL_DefView) return FALSE;
HWND hWndSysListView32 = FindWindowExW(hWndSHELLDLL_DefView, NULL, L"SysListView32", L"FolderView");
if (!hWndSysListView32) return FALSE;
int nCount = (int)SendMessageW(hWndSysListView32, LVM_GETITEMCOUNT, NULL, NULL);
if (nCount < 1) return FALSE;
// 向桌面进程申请缓存区
DWORD dwPid = 0;
GetWindowThreadProcessId(hWndSysListView32, &dwPid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (!hProcess) return FALSE;
LVITEM *_lvi = (LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
if (!_lvi)
{
CloseHandle(hProcess);
return FALSE;
}
PWCHAR _item = (PWCHAR)VirtualAllocEx(hProcess, NULL, MAX_PATH * sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE);
if (!_item)
{
VirtualFreeEx(hProcess, _lvi, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}
// 循环获取桌面项的名称
LVITEM lvi = { 0 };
WCHAR item[MAX_PATH] = { 0 };
LRESULT result = 0;
BOOL bRet = FALSE;
for (int i = 0; i < nCount; i++)
{
lvi.mask = LVIF_TEXT;
lvi.pszText = _item;
lvi.cchTextMax = MAX_PATH;
WriteProcessMemory(hProcess, _lvi, &lvi, sizeof(LVITEM), NULL);
result = SendMessageW(hWndSysListView32, LVM_GETITEMTEXT, (WPARAM)i, (LPARAM)_lvi);
ReadProcessMemory(hProcess, _item, item, MAX_PATH * sizeof(WCHAR), NULL);
// 标记目标项为选中状态
if (!wcscmp(item, pName))
{
lvi.mask = LVIF_STATE;
lvi.state = LVIS_FOCUSED | LVIS_SELECTED;
lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
WriteProcessMemory(hProcess, _lvi, &lvi, sizeof(LVITEM), NULL);
result = SendMessageW(hWndSysListView32, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)_lvi);
// 发送按下回车键
SendMessageW(hWndSysListView32, WM_KEYDOWN, VK_RETURN, 0);
SendMessageW(hWndSysListView32, WM_KEYUP, VK_RETURN, 0);
bRet = TRUE;
break;
}
}
// 释放申请的缓存区
VirtualFreeEx(hProcess, _lvi, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, _item, 0, MEM_RELEASE);
CloseHandle(hProcess);
return bRet;
}