大家好,我是KookNut39,在CSDN写文,分享一些自己认为在学习过程中比较重要的东西,希望可以帮助你进步。最近在更新C/C++方面的知识,感兴趣的可以欢迎关注博主,去专栏查看之前的文章,希望未来能和大家共同探讨技术。
我相信对于很多学习C++的同学来说,在初学阶段都比较疑惑的一个问题就是,我学这个东西可以干什么?就是为了输出“Hello World”吗?好像学了一堆东西总觉得学的云里雾里,不知道自己能干点什么。变量我知道,数据结构我也了解,类我也学习过,指针我也看过,STL标准模板库老师也讲过,但是这些东西在一起可以干什么?
今天就让kt来带大家动手实践一下,以便提高大家学习的热情,写一段代码C/C++代码在windows系统上,实现所有进程遍历,也就是一个破产乞丐版任务管理器。
默认大家都已经掌握了一定的C/C++编程水平,但是掌握度不高也没关系,照着步骤来,你也一定可以实现进程遍历的操作。
我们首先从main函数开始讲起:
int main()
{
//设置地域化信息,设置中文,能够识别中文
setlocale(LC_ALL, "chs");
char* v1 = (char*)("进程枚举:");
printf("%s\n", v1);
//枚举进程的函数
EnumSystemProcess();
system("pause");
system("cls");
system("pause");
return 0;
}
首先我们在main函数中调用了一个设置地域化信息的setlocale函数,因为我们在文中要输出中文。接着就是打印一个字符串,这些都不是重要的代码,接下来调用EnumSystemProcess()函数,这是个自己实现的函数,从这里开始遍历进程:
//枚举系统进程 拍摄快照
HANDLE SnapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (SnapHandle == INVALID_HANDLE_VALUE)
{
return;
}
这是EnumSystemProcess首先要做的事情,那就是拍摄系统快照,拍摄系统快照的函数是CreateToolhelp32Snapshot,传参为TH32CS_SNAPPROCESS的时候就会返回进程快照的句柄,接下来:
//PROCESSENTRY32 必须这样初始化
PROCESSENTRY32 ProcessEntry = { sizeof(PROCESSENTRY32) };
bool IsOk = ProcessFirst(SnapHandle, &ProcessEntry);
PROCESSENTRY32是一个包含在tlhelp32.h头文件下的系统结构体,其中包含了这些信息:
typedef struct tagPROCESSENTRY32
{
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID; // this process
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID; // associated exe
DWORD cntThreads;
DWORD th32ParentProcessID; // this process's parent process
LONG pcPriClassBase; // Base priority of process's threads
DWORD dwFlags;
CHAR szExeFile[MAX_PATH]; // Path
} PROCESSENTRY32;
其中关键的字段官方结构体都已经给出了注释,我们需要用到的也就是取其中的th32ProcessID和szExeFile,因为我们只打印进程名和进程ID。
然后是ProcessFirst函数,这是我自实现的函数,其中为了越过系统空闲进程
进程ID为0:
BOOL ProcessFirst(HANDLE SnapHandle, PPROCESSENTRY32 ProcessEntry)
{
BOOL IsOk = Process32First(SnapHandle, ProcessEntry);
if (IsOk && (ProcessEntry->th32ProcessID == 0))
{
//如果PID = 0,那就byebye 继续去找下一个进程的ProcessEntry
IsOk = ProcessNext(SnapHandle, ProcessEntry);
}
return IsOk;
}
然后在其中调用Process32First这个系统函数,为了得到第一个进程的ProcessEntry,如果当前进程id为0,那就继续遍历,去找下一个进程:
BOOL ProcessNext(HANDLE SnapHandle, PPROCESSENTRY32 ProcessEntry)
{
BOOL IsOk = Process32Next(SnapHandle, ProcessEntry);
if (IsOk && (ProcessEntry->th32ProcessID == 0))
{
//递归调用
IsOk = ProcessNext(SnapHandle, ProcessEntry);
}
return IsOk;
}
在这里我们调用Process32Next去得到下一个进程的PPROCESSENTRY32结构信息,然后进行ID判断,如果不是ID=0,那就返回。返回到EnumSystemProcess的调用处,接下来执行for循环来遍历打印就ok了
//索引 为了统计当前进程总数
int Index = 0;
for (; IsOk; IsOk = ProcessNext(SnapHandle, &ProcessEntry))
{
char BufferData[1024];
//c:\\windows\\hello.exe 寻找'\\'最后出现的位置
char* ProcessName = strrchr(ProcessEntry.szExeFile, '\\');
if (ProcessName == NULL)
{
ProcessName = ProcessEntry.szExeFile;
}
else
{
ProcessName++; //越过反斜杠
}
sprintf(BufferData, "%-50s% (0x%08X)", ProcessName, ProcessEntry.th32ProcessID);
printf("%s\n", BufferData);
Index++;
}
printf("当前系统进程总共有 %d 个\n", Index);
给大家看一下效果图:
整个遍历进程的实现就到这里结束了,如果大家还有不懂得地方,没关系,可以随时联系我,我来帮大家解答,或者有需要源码的小伙伴,也可以找我拿欧!
喜欢博主的文章,麻烦给个一键三连支持一下🤞🤞🤞,您的支持,是我最大的创作动力!
今日份共勉:“相逢意气为君饮,系马高楼垂柳边”