进程控制
1、获取系统进程
2、终止当前进程
3、终止其他进程
4、保护进程
5、进程内存空间说明
6、读进程内存空间
7、写进程内存空间
1、获取系统进程
CreateToolhelp32Snapshot用于获取系统内指定进程的快照
HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
dwFlags指定获取的列表类型
th32ProcessID进程ID,指定那个进程,当获取系统进程列表或当前进程时取0
函数执行成功,返回一个快照句柄,否则返回INVALID_HANDLE_VALUE
| TH32CS_SNAPHEAPLIST | 枚举th32ProcessID参数指定的进程中的堆 |
| TH32CS_SNAPMODULE | 枚举th32ProcessID参数指定的进程中的模块 |
| TH32CS_SNAPPROCESS | 枚举系统范围内的进程,此时th32ProcessID被忽略 |
| TH32CS_SNAPTHREAD | 枚举系统范围内的线程,此时th32ProcessID被忽略 |
从快照列表中获取进程信息使用Process32First和Process32Next函数,每次调用仅返回一个进程的信息。当不再有剩余信息时,函数返回FALSE.
BOOL WINAPI Process32First(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
BOOL WINAPI Process32Next(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
LPPROCESSENTRY32 结构体
typedef struct tagPROCESSENTRY32
{
DWORD dwSize; // 结构体的长度,预先设置
DWORD cntUsage; // 进程的引用计数
DWORD th32ProcessID; // 进程ID
ULONG_PTR th32DefaultHeapID; // 进程默认的堆
DWORD th32ModuleID; // 进程模块ID
DWORD cntThreads; // 进程创建的线程数
DWORD th32ParentProcessID; // 进程的父进程ID
LONG pcPriClassBase; // 进程创建的线程的基本优先级
DWORD dwFlags; // 内部使用
TCHAR szExeFile[MAX_PATH]; // 进程对应可执行文件名
}PROCESSENTRY32,*PPROCESSENTRY32;
例子
#define _AFXDLL
#include <afx.h>
#include <TlHelp32.h> // 声明快照函数的头文件
int main()
{
// 使用这个结构体之前,先设置它的大小
PROCESSENTRY32 pe32;
// 给系统内的所有进程拍一个快照
pe32.dwSize = sizeof(pe32);
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot调用失败!\n");
return -1;
}
// 遍历快照,轮流显示每个进程的信息
BOOL bMore = ::Process32First(hProcessSnap,&pe32);
while(bMore)
{
printf("进程名称:%s\n",pe32.szExeFile);
printf("进程ID:%u\n",pe32.th32ProcessID);
bMore = ::Process32Next(hProcessSnap,&pe32);
}
// 清除snapshot对象
::CloseHandle(hProcessSnap);
system("pause");
return 0;
}
** 2、终止当前进程**
终止当前进程就是进程如何终止自己的运行。方法有两个
-- 主线程的入口函数返回,返回时,启动函数调用exit,并将用户的返回值传给它。exit销毁所有全局的和静态的对象,然后调用ExitProcess促使OS终止应用程序。
-- 程序也可以显式调用ExitProcess,但这样做无法销毁全局的和静态的对象。
void ExitProcess(UINT uExitCode);
捕获进程(已结束)退出的代码
BOOL GetExitCodeProcess(HANDLE hProcess,LPDWORD lpExitCode);
hProcess[in] Handle to the process
lpExitCode[in] Pointer to 32-bit variable to receive the process termination status.
lpExitCode用于装载进程退出代码的一个长整数变量。如进程尚未终止,则取得常数STILL_ACTIVE。
退出代码也称为进程的返回值,该值存储于进程内核对象中。
3、终止其他进程
BOOL TerminateProcess(HANDLE hProcess , DWORD uExitCode);
hProcess : 指定被终止的进程句柄
uExitCode : 指定目标进程的退出代码,也可以使用GetExitCodeProcess取得一个进程的退出代码。
取得进程句柄的两种方法
-- CreateProcess 会返回进程句柄
-- 对于一个已存在的进程,首先得到其进程ID,然后使用OpenProcess取得这个进程的访问权限。
HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
dwDesiredAccess:想得到的访问权限,PROCESS_ALL_ACCESS
bInheritHandle:指定返回句柄是否可被继承
dwProcessId:指定要打开的进程ID
返回进程的句柄
OpenProcess执行失败后返回NULL,这时可进一步调用GetLastError取得错误代码。
例子
#include <stdio.h>
#include <Windows.h>
// 通过进程ID终止进程
BOOL TerminateProcessFromID(DWORD dwID)
{
BOOL bRet = FALSE;
// 打开进程
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwID);
if(hProcess !=NULL)
{
// 终止进程
bRet = ::TerminateProcess(hProcess,0);
}
// 关闭进程句柄
CloseHandle(hProcess);
return bRet;
}
// 测试程序
int main()
{
DWORD dwId;
printf("请输入进程号\n");
scanf("%u",&dwId);
// 通过进程ID终止进程
if (TerminateProcessFromID(dwId))
{
printf("进程终止成功\n");
}
else
{
printf("进程终止失败\n");
}
system("pause");
return 0;
}
4、进程内存空间说明
32位OS可寻址4GB的地址空间,也就是OS的虚拟内存空间位4G,win2000开始,64K--2G给应用程序预留,2G--4G为OS预留,0--64K不被映射,目的是为了捕捉程序种的错误。
每个进程占用的内存空间是离散的,所以要访问进程内存中的一个值,就需要遍历整个64K---2G的地址空间。
Windows采用分页机制管理内存,每页的大小为4K(X86处理器上),也就是说Windows以4K为单位为应用程序分配内存。
5、读进程内存空间
BOOL ReadProcessMemory(HANDLE hProcess , LPCVOID lpBaseAddress , LPVOID lpBuffer , DWORD nSize , LPDWORD lpNumberOfBytesRead);
hProcess:待读进程句柄
lpBaseAddress:目标进程待读内存起始地址
lpBuffer:用来接收读取数据的缓冲区
nSize:要读取的字节数
lpNumberOfBytesRead:实际读取的字节数
6、写进程内存空间
BOOL WriteProcessMemory(HANDLE hProcess , LPCVOID lpBaseAddress , LPVOID lpBuffer , DWORD nSize , LPDWORD lpNumberOfBytesWritten);
参数含义与ReadProcessMemory相同
typedef void* LPVOID
typedef CONST void* LPCVOID
typedef DWORD* LPDWORD
typedef unsigned long DWORD; 32-bit unsigned integer;
网友评论