Toolhelp API 简介

Toolhelp API 简介  

  Toolhelp APIs是Windows中一组能够方便得到系统中win32应用程序的当前运行状况的函数,这些函数设计目的是实现一些基于Win32子系统的工具,特别是调试器。通过使用Toolhelp API,我们可以实现象Windows附带的系统工具Dr watson一样的功能(当然真正实现它的所有功能不是光靠Toolhelp API一个函数库就可以的)。而且这些函数适用于win9x,winnt,win2k,所以不需要为在不同的windows版本中移植代码操心。

  下面将介绍ToolHelp APIs中一些主要的函数和结构。主要有CreateToolhelp32Snapshot和Xxx32First,Xxx32Next系列函数,还有Toolhelp32ReadProcessMemory。所用语言为Object Pascal,对于使用C++的程序员可以参考SDK index中的tool help library [Win32].

以下是它们的定义和说明:

1. 创建快照函数CreateToolhelp32Snapshot

HANDLE WINAPI CreateToolhelp32Snapshot(

DWORD dwFlags, // 要得到进程的信息,赋为TH32CS_SNAPPROCESS

// 要得到线程的信息,赋为TH32CS_SNAPTHREAD

// 要得到指定进程的堆列表,赋为TH32CS_SNAPHEAPLIST

// 要得到指定进程的模块列表,赋为TH32CS_SNAPMODULE

DWORD th32ProcessID // 当我们把dwFlags赋为TH32CS_SNAPMODULE 或者

// TH32CS_SNAPHEAPLIST时,需要指定具体的进程ID,否则

// 将忽略此参数。把它赋为0表示当前进程(也就是自己)

);// 返回值THandle将在以后要枚举进程、线程等对象时使用

当我们得到快照的句柄后可以分别使用Xxx32First,Xxx32Next这些函数进行对象枚举。

它们的定义如下所示:

2. Xxx32First,Xxx32Next枚举函数与有关结构

l 进程有关的函数与结构

typedef struct tagPROCESSENTRY32 {

DWORD dwSize; // 指定结构的大小,

// 在调用Process32First前需要设置,否则将会失败

DWORD cntUsage; // 引用计数

DWORD th32ProcessID; // 进程号

DWORD th32DefaultHeapID; // 进程的堆号,只对Toolhelp函数有意义,并不是一个有效句柄

DWORD th32ModuleID; // 进程的模块号,只对Toolhelp函数有意义,并不是一个有效句柄

DWORD cntThreads; // 进程中包括的线程数

DWORD th32ParentProcessID; // 进程的母进程

LONG pcPriClassBase; // 进程的线程的基优先级,所有此进程创建的线程将基于此优先级

DWORD dwFlags; // 保留,没有使用

char szExeFile[MAX_PATH]; // 进程所对应的文件及路径

} PROCESSENTRY32;

typedef PROCESSENTRY32 * PPROCESSENTRY32;

typedef PROCESSENTRY32 * LPPROCESSENTRY32;

BOOL WINAPI Process32First(

hSnapshot: THandle; // 前面由CreateToolhelp32Snapshot创建的快照句柄

var lppe: TProcessEntry32 //函数输出进程信息

): BOOL; //调用成功将为True,否则为False

BOOL WINAPI Process32Next(hSnapshot: THandle; var lppe: TProcessEntry32): BOOL;

l 模块有关的函数和结构

typedef struct tagMODULEENTRY32 {

DWORD dwSize; // 指定结构的大小,

// 在调用Module32First前需要设置,否则将会失败

DWORD th32ModuleID; // 模块号

DWORD th32ProcessID; // 包含本模块的进程号

DWORD GlblcntUsage; // 本模块的全局引用计数

DWORD ProccntUsage; // 包含模块的进程上下文中的模块引用计数

BYTE * modBaseAddr; // 模块基地址

DWORD modBaseSize; // 模块大小(字节数)

HMODULE hModule; // 包含模块的进程上下文中的hModule句柄.注意:modBaseAddr 与 hModule 只在th32ProcessID的上下文才有效

char szModule[MAX_MODULE_NAME32 + 1]; //模块名

char szExePath[MAX_PATH]; //模块对应的文件名和路径

} MODULEENTRY32;

typedef MODULEENTRY32 * PMODULEENTRY32;

typedef MODULEENTRY32 * LPMODULEENTRY32;

BOOL WINAPI Module32First(hSnapshot: THandle; var lpme: TModuleEntry32): BOOL; //同进程说明

BOOL WINAPI Module32Next(hSnapshot: THandle; var lpme: TModuleEntry32): BOOL;

l 线程有关的函数和结构

typedef struct tagTHREADENTRY32{

DWORD dwSize; // 指定结构的大小,

// 在调用Thread32First前需要设置,否则将会失败

DWORD cntUsage; // 线程引用计数

DWORD th32ThreadID; // 线程号

DWORD th32OwnerProcessID; // 拥有线程的进程号

LONG tpBasePri; // 在线程创建时的初始优先级

LONG tpDeltaPri; // 现在线程的优先级的相对于初始值的改变量

DWORD dwFlags; // 保留,没有使用

} THREADENTRY32;

typedef THREADENTRY32 * PTHREADENTRY32;

typedef THREADENTRY32 * LPTHREADENTRY32;

BOOL WINAPI Thread32First(hSnapshot: THandle; var lpte: TThreadEntry32): BOOL; stdcall;

BOOL WINAPI Thread32Next(hSnapshot: THandle; var lpte: TThreadENtry32): BOOL; stdcall;

l 堆有关的函数和结构

typedef struct tagHEAPENTRY32

{

DWORD dwSize; // 指定结构的大小,在调用Heap32First前需要设置,否则将会失败

HANDLE hHandle; // 堆的句柄

DWORD dwAddress; // 堆起始位置的线性地址

DWORD dwBlockSize; // 堆的大小(字节数)

DWORD dwFlags; // 标志,为以下值:LF32_FIXED 堆内存块的位置是固定的;LF32_FREE 堆内存块没有使用;LF32_MOVEABLE

//堆内存块的位置是可移动的

DWORD dwLockCount; // 堆的锁定计数,每次对堆的执行GlobalLock. 或者LocalLock都将使它增1

DWORD dwResvd; // 保留,没有使用

DWORD th32ProcessID; // 拥有本堆的进程号,这个ID是可以被其他WIN32 API使用的。

DWORD th32HeapID; // 堆号,只能在ToolHelp API中内部使用,

} HEAPENTRY32;

typedef HEAPENTRY32 * PHEAPENTRY32;

typedef HEAPENTRY32 * LPHEAPENTRY32;

BOOL WINAPI Heap32First(

LPHEAPENTRY32 lphe,

DWORD th32ProcessID,

DWORD th32HeapID

);

BOOL WINAPI Heap32Next(

LPHEAPENTRY32 lphe

);

3. 更为有用的Toolhelp API函数有Toolhelp32ReadProcessMemory,它可以读其他进程内存空间的内容。

BOOL WINAPI Toolhelp32ReadProcessMemory(

DWORD th32ProcessID, // 指定进程

LPCVOID lpBaseAddress, // 要读的进程内存空间的起始地址

LPVOID lpBuffer, // 将要读的内容的保存缓冲区

DWORD cbRead, // 要读的字节数

LPDWORD lpNumberOfBytesRead // 成功读取的字节数

); // 函数成功返回True,否则返回False

利用上面的函数,我们得出以下的程序端:

首先我们应该调用CreateToolhelp32Snapshot创建快照;然后调用Process32First,把创建的快照的句柄传递给hSnapshot参数,函数成功返回后我们将在lppe参数中得到第一个进程的信息;继续调用Process32Next,我们将得到后续的进程信息,直到Process32Next返回False为止。记住最后我们应该调用CloseHandle把快照的句柄安全的释放。 根据进程名找到进程ID,然后使用EnumWindows进行获取句柄。

 EnumWindows函数功能:该函数枚举所有屏幕上的顶层窗口,办法是先将句柄传给每一个窗口,然后再传送给应用程序定义的回调函数。EnumThreadWindows函数继续到所有顶层窗口枚举完为止或回调函数返回FALSE为止函数原型:

  BOOL EnumWindows(WNDENUMPROC lpEnumFunc,LPARAM lParam);

  参数:

  lpEnumFunc:指向一个应用程序定义的回调数指针,请参看EnumWindowsProc。

  lPararm:指定一个传递给回调函数的应用程序定义值。

  返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。

// 列出所有进程
void CProcess::SysListProcess()
{
// 初始化
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
// 获得句柄
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == (HANDLE)-1)
{
printf("\nCreateToolhelp32Snapshot()failed:%d",GetLastError());
return;
}
pe32.dwSize = sizeof(PROCESSENTRY32);

// 列举所有进程名称
if (Process32First(hProcessSnap, &pe32))
{
for (int i = 0; Process32Next(hProcessSnap, &pe32); i++)
{
// 将进程名加到列表中
m_list.InsertItem(i, pe32.szExeFile); // CListCtrl m_list;
}
}
else
{
printf("\nProcess32Firstt() failed:%d",GetLastError());
}
// 关闭句柄
CloseHandle (hProcessSnap);
}

你可能感兴趣的:(windows,D语言,pascal)