使用 NtQuerySystemInformation 遍历进程信息

在 Windows 操作系统中,了解正在运行的进程的信息对于系统管理和性能优化至关重要。通过遍历系统进程信息,我们可以获取进程的 ID、名称、线程数、句柄数以及各种性能指标,从而帮助我们了解系统的运行状况并进行必要的调整和优化。本文将详细介绍一种通过调用 Windows 系统API来遍历系统进程信息的技术,同时提供一段用 C++ 编写的示例代码。

操作原理

Windows 操作系统提供了一系列API函数,可以用于获取系统状态和信息。其中之一是 NtQuerySystemInformation 函数,该函数可以用来获取各种系统信息,包括进程信息。通过调用 NtQuerySystemInformation 函数,并将系统信息结构体填充到提供的缓冲区中,我们可以获得系统中运行的所有进程的信息。

在示例代码中,首先定义了一系列结构体,用于存储进程和线程的详细信息。然后通过调用 NtQuerySystemInformation 函数来获取系统进程信息,遍历返回的进程信息结构体,逐个获取每个进程的信息,包括进程名、进程ID、句柄数、线程数等,并在控制台输出。

具体实现

示例代码中使用了以下关键技术:

  • 使用 NtQuerySystemInformation 函数获取系统进程信息。
  • 遍历返回的进程信息结构体,获取每个进程的详细信息。
  • 输出获取到的进程信息到控制台。

示例代码解析

以下是示例代码中用到的关键部分:

  • 定义了用于存储进程信息的 _SYSTEM_PROCESS_INFORMATION 结构体和用于存储线程信息的 _SYSTEM_THREAD_INFORMATION 结构体。
  • 使用 NtQuerySystemInformation 函数获取系统进程信息,并遍历返回的进程信息结构体,逐个获取每个进程的信息并输出到控制台。

完整代码

#include <iostream>
#include <Windows.h>#ifdef _WIN64
typedef ULONG64 KPRIORITY;
#else
typedef LONG KPRIORITY;
#endif
#define SystemProcessInformation    5 // 功能号#ifdef _M_IX86
typedef struct _CLIENT_ID
{DWORD        UniqueProcess;DWORD        UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
#endif // x86模式下#ifdef _M_X64
typedef struct _CLIENT_ID
{ULONG64        UniqueProcess;ULONG64        UniqueThread;
} CLIENT_ID, * PCLIENT_ID;
#endif // x64模式下typedef struct _UNICODE_STRING {USHORT Length;USHORT MaximumLength;PWSTR  Buffer;
} UNICODE_STRING, * PUNICODE_STRING;typedef enum _KWAIT_REASON
{Executive = 0,FreePage = 1,PageIn = 2,PoolAllocation = 3,DelayExecution = 4,Suspended = 5,UserRequest = 6,WrExecutive = 7,WrFreePage = 8,WrPageIn = 9,WrPoolAllocation = 10,WrDelayExecution = 11,WrSuspended = 12,WrUserRequest = 13,WrEventPair = 14,WrQueue = 15,WrLpcReceive = 16,WrLpcReply = 17,WrVirtualMemory = 18,WrPageOut = 19,WrRendezvous = 20,Spare2 = 21,Spare3 = 22,Spare4 = 23,Spare5 = 24,WrCalloutStack = 25,WrKernel = 26,WrResource = 27,WrPushLock = 28,WrMutex = 29,WrQuantumEnd = 30,WrDispatchInt = 31,WrPreempted = 32,WrYieldExecution = 33,WrFastMutex = 34,WrGuardedMutex = 35,WrRundown = 36,MaximumWaitReason = 37
} KWAIT_REASON;// 线程结构体
typedef struct _SYSTEM_THREAD_INFORMATION
{LARGE_INTEGER KernelTime;LARGE_INTEGER UserTime;LARGE_INTEGER CreateTime;ULONG WaitTime;PVOID StartAddress;CLIENT_ID ClientId;KPRIORITY Priority;LONG BasePriority;ULONG ContextSwitches;ULONG ThreadState;KWAIT_REASON WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;// 进程结构体
typedef struct _SYSTEM_PROCESS_INFORMATION
{ULONG NextEntryOffset;ULONG NumberOfThreads;LARGE_INTEGER WorkingSetPrivateSize; // since VISTAULONG HardFaultCount; // since WIN7ULONG NumberOfThreadsHighWatermark; // since WIN7ULONGLONG CycleTime; // since WIN7LARGE_INTEGER CreateTime;LARGE_INTEGER UserTime;LARGE_INTEGER KernelTime;UNICODE_STRING ImageName;KPRIORITY BasePriority;HANDLE UniqueProcessId;HANDLE InheritedFromUniqueProcessId;ULONG HandleCount;ULONG SessionId;ULONG_PTR UniqueProcessKey; // since VISTA (requires SystemExtendedProcessInformation)SIZE_T PeakVirtualSize;SIZE_T VirtualSize;ULONG PageFaultCount;SIZE_T PeakWorkingSetSize;SIZE_T WorkingSetSize;SIZE_T QuotaPeakPagedPoolUsage;SIZE_T QuotaPagedPoolUsage;SIZE_T QuotaPeakNonPagedPoolUsage;SIZE_T QuotaNonPagedPoolUsage;SIZE_T PagefileUsage;SIZE_T PeakPagefileUsage;SIZE_T PrivatePageCount;LARGE_INTEGER ReadOperationCount;LARGE_INTEGER WriteOperationCount;LARGE_INTEGER OtherOperationCount;LARGE_INTEGER ReadTransferCount;LARGE_INTEGER WriteTransferCount;LARGE_INTEGER OtherTransferCount;//SYSTEM_THREAD_INFORMATION Threads[1];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;// 定义函数声明
typedef NTSTATUS (WINAPI* __QuerySystemInformation) (UINT systemInformation,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength
);BOOL QueryProcessInformationCallAll() {ULONG cbSize = sizeof(SYSTEM_PROCESS_INFORMATION);__QuerySystemInformation NtQuerySystemInformation = NULL;HMODULE hNtDll = GetModuleHandleW(L"ntdll.dll");if (hNtDll == NULL){wprintf(L"LoadLibrary Failed.\n");return FALSE;}NtQuerySystemInformation = (__QuerySystemInformation)GetProcAddress(hNtDll, "NtQuerySystemInformation");PSYSTEM_PROCESS_INFORMATION sysPSIEntry = NULL, sysForwardLinks = NULL;if (NtQuerySystemInformation == NULL) {wprintf(L"GetProcAddress Failed.\n");return FALSE;}// 调用 NtQuerySystemInformation 查询进程信息NTSTATUS status = 0;status = NtQuerySystemInformation(SystemProcessInformation, NULL, 0, &cbSize);if (status == 0xC0000004){sysPSIEntry = (PSYSTEM_PROCESS_INFORMATION)malloc(cbSize);status = NtQuerySystemInformation(SystemProcessInformation, sysPSIEntry, cbSize, &cbSize);if (status)free(sysPSIEntry);}// 拷贝结构体指针副本sysForwardLinks = sysPSIEntry;// 使用指针副本遍历进程信息while (sysForwardLinks->NextEntryOffset != 0){if (sysForwardLinks->ImageName.Buffer != NULL){wprintf(L"进程名:\t%s \t进程ID:%I64u \t句柄总数:%u \t线程总数:%u \n", sysForwardLinks->ImageName.Buffer, (UINT64)sysForwardLinks->UniqueProcessId,sysForwardLinks->HandleCount, sysForwardLinks->NumberOfThreads);// 打印线程信息PSYSTEM_THREAD_INFORMATION threadInfo = NULL;threadInfo = (PSYSTEM_THREAD_INFORMATION)((UINT64)sysForwardLinks + sizeof(SYSTEM_PROCESS_INFORMATION));DWORD curThreadIndex = 1;do {
#ifdef _WIN64wprintf(L"\t线程ID:%I64u \t起始地址:0x%I64X \t线程的状态码:%u\n", threadInfo->ClientId.UniqueThread, (UINT64)threadInfo->StartAddress, threadInfo->ThreadState);
#elsewprintf(L"\t线程ID:%d \t起始地址:0x%I32X \t线程的状态码:%u\n",threadInfo->ClientId.UniqueThread,(UINT)threadInfo->StartAddress,threadInfo->ThreadState);
#endif++threadInfo;} while (curThreadIndex++ < sysForwardLinks->NumberOfThreads);wprintf(L"\n");}// 指针的加减运算的单位是根据所指向数据类型大小的。// 字节指针就是1,所以加减运算没问题。// 这里是结构体指针,所以必须转成数字类型再运算。sysForwardLinks = (PSYSTEM_PROCESS_INFORMATION)((UINT64)sysForwardLinks + sysForwardLinks->NextEntryOffset);}// 释放内存free(sysPSIEntry);sysPSIEntry = NULL;sysForwardLinks = NULL;return TRUE;
}int main()
{setlocale(LC_ALL, ".utf8");// 转换控制台代码页编码为 UTF-8QueryProcessInformationCallAll();return 0;
}

测试结果截图:

结果截图 1

总结

通过遍历系统进程信息,我们可以了解系统中运行的各种进程的详细信息,从而更好地进行系统管理和性能优化。本文介绍了一种通过调用 Windows 系统API来获取并遍历系统进程信息的技术,并提供了一段示例代码以帮助读者理解该技术的实现方法。希望本文对于对 Windows 系统进程信息感兴趣的读者有所帮助。


发布于:2024.02.07,更新于:2024.02.07

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/458044.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电力负荷预测 | 电力系统负荷预测模型(Python线性回归、随机森林、支持向量机、BP神经网络、GRU、LSTM)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 电力系统负荷预测模型(Python线性回归、随机森林、支持向量机、BP神经网络、GRU、LSTM) 所谓预测,就是指通过对事物进行分析及研究,并运用合理的方法探索事物的发展变化规律,对其未来发展做出预先估计和判断。…

Linux 文件比较工具

在Linux系统中&#xff0c;文件比较是一种常见的任务&#xff0c;用于比较两个文件之间的差异。文件比较可以帮助我们找出两个文件的不同之处&#xff0c;或者确定它们是否完全相同。在Linux中&#xff0c;有多种方法可以进行文件比较。 1. diff 在Linux中&#xff0c;diff命…

力扣53. 最大子数组和(滑动窗口,动态规划)

Problem: 53. 最大子数组和 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 思路1:滑动窗口 1.为求出最大连续的子数组和,我们逻辑上假设有一个窗口在原数组上滑动, 欲求出最大连续,则需要保证窗口中的所有元素和最起码大于0; 2.即当当前窗口中的元素值的和小于0…

jsp课程管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 课程管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

BUGKU-WEB Flask_FileUpload

题目描述 进入场景后&#xff0c;就是一个简单的上传界面&#xff1a; 解题思路 即然是文件上传&#xff0c;那必须要上传后门来获取一些信息。一般会有过滤规则&#xff0c;那必须利用好这个规则来操作。准备好你的马马&#xff0c;准备策马奔腾吧 相关工具 略 解题步骤…

Java Map HashMap集合的基本操作与使用

Java Map HashMap集合的基本操作与使用 package com.zhong.mapdemo.map;import jdk.jfr.Description;import javax.swing.plaf.synth.SynthOptionPaneUI; import java.util.*;/*** ClassName : MapDemo* Description : map 的基本使用* Author : zhx* Date: 2024-02-07 10:29*/…

白酒:生产过程中的质量控制与食品安全

在豪迈白酒的生产过程中&#xff0c;质量控制与食品安全是至关重要的环节。云仓酒庄深知这一点&#xff0c;并采取了一系列严格的质量控制措施&#xff0c;确保产品的安全与品质。 首先&#xff0c;云仓酒庄对原料的选择非常严格。酒庄与可靠的供应商建立了长期合作关系&#x…

Oracle篇—logminer日志挖掘恢复误操作数据

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux&#xff0c;也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&#xff0c;并且也会默默的点赞收藏加关注❣…

【华为 ICT HCIA eNSP 习题汇总】——题目集13

1、以下在项目规划阶段中需要完成的工作是&#xff08;&#xff09;。 A、确定技术方案 B、了解项目背景 C、选择网络产品 D、规划 IP 地址 考点&#xff1a;网络规划与设计 解析&#xff1a;&#xff08;B&#xff09; 确定技术方案是在网络规划的设计阶段完成的工作&#xff…

计算机毕业设计 | SpringBoot大型旅游网站 旅行后台管理系统(附源码)

1&#xff0c; 概述 1.1 项目背景 随着互联网技术的快速发展和普及&#xff0c;旅游行业逐渐转向线上&#xff0c;越来越多的游客选择在线预订旅游产品。传统的线下旅行社模式已不能满足市场需求&#xff0c;因此&#xff0c;开发一个高效、便捷的旅游网站成为行业的迫切需求…

Android 13.0 原生SystemUI下拉通知栏每条通知默认展开

1.前言 在13.0的系统rom原生开发中,在在对SystemUI下拉通知栏做定制的时候,在下拉状态栏的时候,通知栏中最后一条通知默认是收缩的 点击按钮 就会展开 原生系统systemui就是如此,为了更美观 所以要求最后一条通知也默认展开,显得更美观 最终效果图: 2.原生SystemUI下拉通…

自行车 - 有风时如何往返骑

许多铁三赛事的骑车段都是在同一个赛道往返骑乘&#xff0c;因此我们会遇到一个问题&#xff0c;如果去程顺风、回程逆风&#xff0c;或是去程逆风、回程逆风&#xff0c;我们应该要如何配速&#xff0c;才能在骑车赛段骑出最佳成绩呢? 当然&#xff0c;有时候也会遇到去程回程…