进程遍历-WTSEnumerateProcesses枚举

进程遍历-WTSEnumerateProcesses枚举

1. 相关函数及结构体

1.1 WTSEnumerateProcesses

​ 检索有关指定远程桌面会话主机 (RD 会话主机) 服务器上的活动进程的信息

BOOL WTSEnumerateProcessesA(
  [in]  HANDLE             hServer,
  [in]  DWORD              Reserved,
  [in]  DWORD              Version,
  [out] PWTS_PROCESS_INFOA *ppProcessInfo,
  [out] DWORD              *pCount
);

​ hServer RD 会话主机服务器的句柄。 指定由 WTSOpenServer 函数打开的句柄,或指定 WTS_CURRENT_SERVER_HANDLE 以指示运行应用程序的 RD 会话主机服务器

​ Reserved 必须为零

​ Version 指定枚举请求的版本,必须为 1。

​ ppProcessInfo 接收指向 WTS_PROCESS_INFO 结构的数组的指针。 数组中的每个结构都包含有关指定 RD 会话主机服务器上的活动进程的信息

​ pCount 接收 ppProcessInfo 缓冲区中返回的WTS_PROCESS_INFO结构的数目

1.2 WTS_PROCESS_INFOA

​ 包含有关远程桌面会话主机 (RD 会话主机) 服务器上运行的进程的信息

typedef struct _WTS_PROCESS_INFOA {
  DWORD SessionId;
  DWORD ProcessId;
  LPSTR pProcessName;
  PSID  pUserSid;
} WTS_PROCESS_INFOA, *PWTS_PROCESS_INFOA;

​ SessionId 与进程关联的会话的远程桌面服务会话标识符

​ ProcessId 唯一标识 RD 会话主机服务器上的进程的进程标识符

​ pProcessName 指向以 null 结尾的字符串的指针,其中包含与进程关联的可执行文件的名称

​ pUserSid 指向进程的主要访问令牌中的用户 安全标识符 的指针

2. 遍历进程

2.1 遍历进程思路分析

  1. 通过WTSEnumerateProcessesW 直接遍历相关信息
  2. 处理进程信息结构体

2.2 遍历进程具体实现

#include <windows.h>
#include <wtsapi32.h>
#include <stdio.h>
#include <locale.h>
#pragma comment(lib, "Wtsapi32.lib")

int main(int argc, char* argv[]) {
	setlocale(LC_ALL, "zh_CN.UTF-8");
	PWTS_PROCESS_INFOW processInfo;
	DWORD pCount;
	WTSEnumerateProcessesW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &processInfo, &pCount);

	for (int index = 0; index < pCount; index++) {
		printf_s("%ws\n", processInfo[index].pProcessName);
	}

	WTSFreeMemory(processInfo);
	return 1;
}

在这里插入图片描述

关注我们,咱们在安全的路上,扬帆起航

在这里插入图片描述

参考文献

[1] https://learn.microsoft.com/zh-cn/windows/win32/api/wtsapi32/nf-wtsapi32-wtsenumerateprocessesa?redirectedfrom=MSDN

[2] https://learn.microsoft.com/zh-cn/windows/win32/api/wtsapi32/ns-wtsapi32-wts_process_infoa

  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include <windows.h> #include <QString> #include <QMessageBox> int main(int argc, char *argv[]) { HANDLE mutex = ::CreateMutex(Q_NULLPTR, true, (LPCWSTR)qApp->applicationName().toStdWString().c_str()); if (GetLastError() == ERROR_ALREADY_EXISTS) { QMessageBox waringBox(QMessageBox::Warning, QStringLiteral("警告"), QStringLiteral("当前程序已运行,不能再次运行!")); waringBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定")); waringBox.setStandardButtons(QMessageBox::Ok); waringBox.exec(); ::CloseHandle(mutex); return 0; } // 获取当前登录用户的会话ID DWORD sessionId; ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); // 遍历所有用户会话,关闭其他用户会话中的该程序进程 DWORD sessionCount; if (ProcessIdToSessionId(GetCurrentProcessId(), &sessionId) && WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTS_INFO_CLASS::WTS_SESSION, (LPWSTR*)&sessionCount, &sessionId)) { WTS_SESSION_INFO* pSessionInfo = NULL; if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &sessionCount)) { for (DWORD i = 0; i < sessionCount; i++) { DWORD processCount; if (WTSEnumerateProcesses(pSessionInfo[i].hServer, pSessionInfo[i].SessionId, 1, (PWTS_PROCESS_INFO*)&processCount)) { WTS_PROCESS_INFO* pProcessInfo = NULL; if (WTSEnumerateProcesses(pSessionInfo[i].hServer, pSessionInfo[i].SessionId, 1, &pProcessInfo, &processCount)) { for (DWORD j = 0; j < processCount; j++) { if (pProcessInfo[j].SessionId != sessionId && wcsstr(pProcessInfo[j].pProcessName, qApp->applicationName().toStdWString().c_str())) { HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, pProcessInfo[j].ProcessId); if (hProcess) { ::TerminateProcess(hProcess, 0); ::CloseHandle(hProcess); } } } ::WTSFreeMemory(pProcessInfo); } } } ::WTSFreeMemory(pSessionInfo); } } // 正常执行程序 QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } 上面代码会报出 error: 'WTS_CURRENT_SERVER_HANDLE' was not declared in this scope错误,请修复后给我完整代码
最新发布
05-30
好的,根据您提供的代码,我发现需要添加一个头文件 `wtsapi32.h` 来解决该错误。修改后的完整代码如下: ``` #include <windows.h> #include <wtsapi32.h> #include <QString> #include <QMessageBox> int main(int argc, char *argv[]) { HANDLE mutex = ::CreateMutex(Q_NULLPTR, true, (LPCWSTR)qApp->applicationName().toStdWString().c_str()); if (GetLastError() == ERROR_ALREADY_EXISTS) { QMessageBox waringBox(QMessageBox::Warning, QStringLiteral("警告"), QStringLiteral("当前程序已运行,不能再次运行!")); waringBox.setButtonText(QMessageBox::Ok, QStringLiteral("确定")); waringBox.setStandardButtons(QMessageBox::Ok); waringBox.exec(); ::CloseHandle(mutex); return 0; } // 获取当前登录用户的会话ID DWORD sessionId; ProcessIdToSessionId(GetCurrentProcessId(), &sessionId); // 遍历所有用户会话,关闭其他用户会话中的该程序进程 DWORD sessionCount; if (ProcessIdToSessionId(GetCurrentProcessId(), &sessionId) && WTSQuerySessionInformationW(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTS_INFO_CLASS::WTS_SESSION, (LPWSTR*)&sessionCount, &sessionId)) { WTS_SESSION_INFO* pSessionInfo = NULL; if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &sessionCount)) { for (DWORD i = 0; i < sessionCount; i++) { DWORD processCount; if (WTSEnumerateProcesses(pSessionInfo[i].hServer, pSessionInfo[i].SessionId, 1, (PWTS_PROCESS_INFO*)&processCount)) { WTS_PROCESS_INFO* pProcessInfo = NULL; if (WTSEnumerateProcesses(pSessionInfo[i].hServer, pSessionInfo[i].SessionId, 1, &pProcessInfo, &processCount)) { for (DWORD j = 0; j < processCount; j++) { if (pProcessInfo[j].SessionId != sessionId && wcsstr(pProcessInfo[j].pProcessName, qApp->applicationName().toStdWString().c_str())) { HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, pProcessInfo[j].ProcessId); if (hProcess) { ::TerminateProcess(hProcess, 0); ::CloseHandle(hProcess); } } } ::WTSFreeMemory(pProcessInfo); } } } ::WTSFreeMemory(pSessionInfo); } } // 正常执行程序 QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } ``` 需要注意的是,添加了 `wtsapi32.h` 的头文件之后,编译时需要链接该库文件 `wtsapi32.lib`,否则会出现 `LNK2019` 错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值