如何监控windows进程的句柄、内存和cpu(一)

假设某天我突发奇想,想要实现:

输入一个进程名字,输出该进程的句柄、内存占用、CPU使用情况。

ok,那我们来看下如何扯出这个程序,以下演示程序基于vs2008,更高版本可能会有字符问题。

 

1)在系统中查找是否存在指定进程名的进程

这里需要用到windows提供的几个API函数:CreateToolhelp32Snapshot、Process32First和Process32Next。

函数的简单介绍:

HANDLE WINAPI CreateToolhelp32Snapshot(
  __in          DWORD dwFlags,
  __in          DWORD th32ProcessID
);

函数功能:创建指定进程的快照,快照包括进程的堆栈、模块、线程;

参数:

dwFlags:获取系统进程快照的类型;当指定为TH32CS_SNAPPROCESS,表示在快照中包括系统中的所有进程,此时将忽略th32ProcessID的设置。

th32ProcessID:指定要获取进程快照的进程ID;为0表示当前进程;此参数只有在dwFlags设置了TH32CS_SNAPHEAPLIST或者TH32CS_SNAPMODULE后才有效。

返回值:当函数调用成功返回快照句柄,否则返回INVALID_HANDLE_VALUE。在得到系统进程快照句柄后,需要调用Process32First函数查找系统进程快照中的第一个进程。

详情:https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot

 

Process32First函数

BOOL WINAPI Process32First(
  __in          HANDLE hSnapshot,
  __in_out      LPPROCESSENTRY32 lppe
);

函数功能:获取进程快照中的第一个进程信息

参数:

hSnapshot:系统进程快照的句柄;

Lppe:指向PROCESSNTRY结构的结构体指针,进程的详细信息保存在此结构体中:

typedef struct tagPROCESSENTRY32 {
  DWORD dwSize;//结构大小
  DWORD cntUsage;//此进程的引用计数
  DWORD th32ProcessID;//进程ID
  ULONG_PTR th32DefaultHeapID;//进程默认堆ID
  DWORD th32ModuleID;//进程模块ID
  DWORD cntThreads;//此进程开启的线程计数
  DWORD th32ParentProcessID;//父进程ID
  LONG pcPriClassBase;//线程优先权
  DWORD dwFlags;//保留
  TCHAR szExeFile[MAX_PATH];//进程名
} PROCESSENTRY32,
 *PPROCESSENTRY32;

返回值:当函数列举到进程时返回true,否则返回false。

详情:https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32first

 

Process32Next函数:

BOOL WINAPI Process32Next(
  __in          HANDLE hSnapshot,
  __in_out      LPPROCESSENTRY32 lppe
);

函数功能:获取进程快照中下一个进程信息;

参数和返回值与Process32Next函数基本一致

详情:https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-process32next


OpenProcess函数:

HANDLE OpenProcess(
    DWORD dwDesiredAccess, //想拥有的该进程的访问权限
    BOOL bInheritHandle, //所得到的进程句柄是否可以被继承
    DWORD dwProcessId//需要被打开的进程的PID
);

函数功能:打开已存在的进程对象,返回进程句柄;

返回值:函数成功,返回指定进程的句柄,失败返回NULL。

详情:https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess

 

具体的实现代码:

std::vector<HANDLE> GetProcessHandle(LPCWSTR lpName)
{
    DWORD dwPid = 0;
    HANDLE hProcess = NULL;
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
    std::vector<HANDLE> hProcessGroup;

    do{
        hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获取系统所有进程的快照
        if (hProcessSnap == INVALID_HANDLE_VALUE)
        {
            //日志
            break;
        }

        pe32.dwSize = sizeof(PROCESSENTRY32);
        if (!Process32First(hProcessSnap, &pe32))//获取第一个进程信息
        {
            //日志
            CloseHandle(hProcessSnap);
            break;
        }


        int namelen = 200;
        char name[201] = { 0 };
        do
        {
            if (NULL != wcsstr(pe32.szExeFile, lpName)) {//查找匹配字符串
                dwPid = pe32.th32ProcessID;
                hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);//获取进程句柄
                hProcessGroup.push_back(hProcess);
            }
        } while (Process32Next(hProcessSnap, &pe32));
        CloseHandle(hProcessSnap);//记得释放句柄
    }while(0);
    return hProcessGroup;
}

这里使用的vector存储多个进程句柄,是因为实际系统中,可能有多个同名的进程,比如Chrome每个页面都是一个进程。

到这里,我们就可以获得的当前系统中指定进程名的所有操作句柄了。


下一篇将介绍如何使用进程句柄获取进程当前的CPU占用

本文为作者原创,如需转载,请在评论区征得作者同意,原创链接:https://blog.csdn.net/anranjingsi/article/details/106104403

原创文章 3 获赞 5 访问量 161

猜你喜欢

转载自blog.csdn.net/anranjingsi/article/details/106104403