VC下通过系统快照实现进程管理的方法

所属分类: 软件编程 / C 语言 阅读数: 104
收藏 0 赞 0 分享

本文实例讲述了VC下通过系统快照实现进程管理的方法,分享给大家供大家参考。具体实现方法如下:

一、引言

  每一个应用程序实例在运行起来后都会在当前系统下产生一个进程,大多数应用程序均拥有可视界面,用户可以通过标题栏上的关闭按钮关闭程序。但是也有为数不少的在后台运行的程序是没有可视界面的,对于这类应用程序用户只能通过CTRL+ALT+DEL热键呼出"关闭程序"对话框显示出当前系统进程列表,从中可以结束指定的任务。显然,该功能在一些系统监控类软件中还是非常必需的,其处理过程大致可以分为两步:借助系统快照实现对系统当前进程的枚举和根据枚举结果对进程进行管理。本文下面即将对此过程的实现进行介绍。

二、当前进程的枚举

  要对当前系统所有已开启的进程进行枚举,就必须首先获得那些加载到内存的进程当前相关状态信息。在Windows操作系统下,这些进程的当前状态信息不能直接从进程本身获取,系统已为所有保存在系统内存中的进程、线程以及模块等的当前状态的信息制作了一个只读副本--系统快照,用户可以通过对系统快照的访问完成对进程当前状态的检测。在具体实现时,系统快照句柄的获取是通过Win32 API函数CreateToolhelp32Snapshot()来完成的,通过该函数不仅可以获取进程快照,而且对于堆、模块和线程的系统快照同样可以获取。该函数原型声明如下:

复制代码 代码如下:
HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID);

  其中,参数dwFlags:指定将要创建包含哪一类系统信息的快照句柄,本程序中只需要检索系统进程信息,因此可将其设置为 TH32CS_SNAPPROCESS;函数第二个参数th32ProcessID`则指定了进程的标识号,当设置为0时指定当前进程。如果成功函数将返回一个包含进程信息的系统快照句柄。在得到快照句柄之后只能以只读的方式对其进行访问。至于对系统快照句柄的使用同普通对象句柄的使用并没有什么太大区别,在使用完之后也需要通过CloseHandle()函数将其销毁。
  在得到系统的快照句柄后,就可以对当前进程的标识号进行枚举了,通过这些枚举出的进程标识号可以很方便的对进程进行管理。进程标识号通过函数 Process32First() 和 Process32Next()而得到,这两个函数可以枚举出系统当前所有开启的进程,并且可以得到相关的进程信息。 这两个函数原型声明如下:

复制代码 代码如下:
BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
BOOL WINAPI Process32Next(HANDLE hSnapshot,LPPROCESSENTRY32 lppe);

  以上两个函数分别用于获得系统快照中第一个和下一个进程的信息,并将获取得到的信息保存在指针lppe所指向的PROCESSENTRY32结构中。函数第一个参数hSnapshot为由CreateToolhelp32Snapshot()函数返回得到的系统快照句柄;第二个参数lppe为指向结构 PROCESSENTRY32的指针,PROCESSENTRY32结构可对进程作一个较为全面的描述,其定义如下:

复制代码 代码如下:
typedef struct tagPROCESSENTRY32 {
DWORD dwSize; // 结构大小;
DWORD cntUsage; // 此进程的引用计数;
DWORD th32ProcessID; // 进程ID;
DWORD th32DefaultHeapID; // 进程默认堆ID;
DWORD th32ModuleID; // 进程模块ID;
DWORD cntThreads; // 此进程开启的线程计数;
DWORD th32ParentProcessID; // 父进程ID;
LONG pcPriClassBase; // 线程优先权;
DWORD dwFlags; // 保留;
char szExeFile[MAX_PATH]; // 进程全名;
} PROCESSENTRY32;

  以上三个API函数均在头文件tlhelp32.h中声明,运行时需要有kernel32.lib库的支持。通过这三个函数可以枚举出当前系统已开启的所有进程,并可获取到进程的各相关信息,下面给出一个简单的应用示例。在此示例中将枚举出系统的所有进程,并获取各进程的标识号和相应程序的绝对路径,进程标识号在下一步对进程的管理中将要用到,程序路径则直接通过列表控件显示出来:

复制代码 代码如下:
// PROCESSENTRY32结构对象
PROCESSENTRY32 pe;
// 创建快照句柄
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
// 先搜索系统中第一个进程的信息
Process32First(hSnapshot, &pe);
// 下面对系统中的所有进程进行枚举,并保存其信息
do{
// 把进程对应的文件路径名填入列表框
int index = m_ctlwndList.AddString(pe.szExeFile);
// 设置列表框中该项的Data相应的进程的ID号,利于以后终止该进程
m_ctlwndList.SetItemData(index, pe.th32ProcessID);
} while (Process32Next(hSnapshot, &pe));
// 关闭快照句柄
CloseHandle(hSnapshot);

三、对进程的管理

  在得到各枚举进程的标识号后就可以实现对进程的管理了,由于被管理进程在当前进程之外,因此必须首先通过OpenProcess()函数来获取一个已经存在的进程对象的句柄,然后才可以通过该句柄对指定的进程进行管理和控制。在OpenProcess()函数的调用时把进程标识号作为参数传入, OpenProcess()函数的原型声明如下:

复制代码 代码如下:
HANDLE OpenProcess(DWORD dwDesiredAccess, // 访问标志
BOOL bInheritHandle, // 处理继承的标志
DWORD dwProcessId // 进程标识号);


  如果函数执行成功将返回由进程标识号指定的进程对象句柄。下面同样也对其给出一个简单的应用示例,在此示例中根据所获取的进程对象句柄通过TerminateProcess()函数将指定的进程终止:

复制代码 代码如下:
// 获得此时列表框中的所选项的数据,即该项对应的进程的ID值
int index = m_ctlwndList.GetCurSel();
// 获得此时列表框中的选项,即该项对应的进程的ID值
DWORD data = m_ctlwndList.GetItemData(index);
// 利用进程的ID值,打开该进程,获得进程句柄
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE,data);
// 检测句柄的有效性,如有效则终止该进程
if (hProcess)
TerminateProcess(hProcess,0);

  由于需要在调用TerminateProcess()函数终止进程时确保进程句柄可有效使用,因此在前面调用OpenProcess()时,需要指定其访问标致为PROCESS_TERMINATE。

四、小结

  本文主要对系统快照以及通过借助系统快照而对系统当前进程进行枚举、管理的实现方法做了简要介绍。在本文只讨论了包含有进程信息的系统快照,感兴趣的读者完全可以用类似的方法实现对包含有线程、堆或是摸块等信息的系统快照的应用。本文所述程序在Windows 98下由Microsoft Visual C++ 6.0编译通过。

希望本文所述对大家的VC程序设计有所帮助。

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多