CProcessUtils.h
#pragma once#include <wtypesbase.h>
#include <tchar.h>
#include <vector>
#include <map>
#include <string>#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif// 进程信息
typedef struct _PROC_INFO
{DWORD dwParentPID; // 父进程IDDWORD dwPID; // 进程ID_tstring strExeFile; // 可执行文件的名称LONG nPriClassBase; // 此进程创建的任何线程的基本优先级DWORD cntThreads; // 进程启动的执行线程
}PROC_INFO;// 模块信息
typedef struct _MODULE_INFO
{_tstring strExePath; // 模块路径_tstring strModule; // 模块名HMODULE hModule; // 拥有进程上下文中模块的句柄BYTE* modBaseAddr; // 拥有进程上下文中模块的基址DWORD modBaseSize; // 模块的大小(以字节为单位)
}MODULE_INFO;// 进程树结点信息
typedef struct _PROCESS_TREE
{DWORD dwPID; // 进程IDDWORD dwParentPID; // 父进程ID_tstring strExeFile; // 可执行文件的名称LONG nPriClassBase; // 此进程创建的任何线程的基本优先级DWORD dwCntThreads; // 进程启动的执行线程std::vector<_PROCESS_TREE> childProcesses; //子进程列表
}PROCESS_TREE;// PE文件头信息
typedef struct _PE_HEADER_INFO
{IMAGE_DOS_HEADER m_DosHeader; //Dos头IMAGE_NT_HEADERS32 m_NtHeaders32; //NT头(32位)IMAGE_NT_HEADERS64 m_NtHeaders64; //NT头(64位)WORD m_NtHeadersMagic; //NT头魔数
}PE_HEADER_INFO;class CProcessUtils
{
public://// @brief: 运行进程// @param: strCmd 命令行// @param: strCurDir 程序的当前目录// @param: bShow 是否显示程序// @param: bWait 是否等待程序直到其退出// @ret: bool 操作是否成功static bool RunProcess(const _tstring& strCmd = _T(""), const _tstring& strCurDir = _T(""), bool bShow = true, bool bWait = true);//// @brief: 获取进程可执行文件路径// @param: dwPID 进程ID// @param: bNtPath 是否为Win32 样式的 NT 路径// @ret: _tstring 进程可执行文件路径static _tstring GetPath(DWORD dwPID, bool bNtPath = true);//// @brief: 获取进程可执行文件路径// @param: dwPID 进程ID// @param: bNtPath 是否为Win32 样式的 NT 路径// @ret: _tstring 进程可执行文件路径static _tstring GetPathEx(DWORD dwPID, bool bNtPath = true);//// @brief: 获取父进程可执行文件路径// @param: dwPID 进程ID// @param: bNtPath 是否为Win32 样式的 NT 路径// @ret: _tstring 进程可执行文件路径static _tstring GetParentPath(DWORD dwPID, bool bNtPath = true);//// @brief: 获取所有进程信息// @ret: std::map<DWORD, PROC_INFO> 进程信息static std::map<DWORD, PROC_INFO> GetAllProcessInfos();//// @brief: 获取指定进程的模块信息(注意: 32位进程不能获取64位进程的模块信息)// @param: dwPID 进程ID// @ret: std::vector<MODULE_INFO> 模块信息static std::vector<MODULE_INFO> GetModuleInfos(DWORD dwPID);//// @brief: 获取进程加载的模块列表(注意: 32位进程不能获取64位进程的模块信息)// @param: dwPID 进程ID// @ret: _tstring 模块列表static std::vector<_tstring> GetModules(DWORD dwPID);//// @brief: 获取指定进程的进程树// @ret: std::map<DWORD, PROC_INFO> 进程信息static PROCESS_TREE GetProcessTree(DWORD dwPID);//// @brief: 获取父进程的进程ID// @param: dwPID 进程ID// @ret: DWORD 父进程的进程IDstatic DWORD GetParentID(DWORD dwPID);//// @brief: 等待进程结束// @param: dwPID 进程ID// @param: dwMilliseconds 超时时间// @ret: bool 操作是否成功static bool WaitForProcess(DWORD dwPID, DWORD dwMilliseconds = INFINITE);//// @brief: 杀死指定进程// @param: dwPID 进程ID// @ret: bool 操作是否成功static bool KillProcess(DWORD dwPID);//// @brief: 杀死进程树中的进程// @param: procTree 进程树// @ret: bool 操作是否成功static bool KillProcessTree(const PROCESS_TREE& procTree);//// @brief: 杀死指定进程ID的进程树// @param: dwPID 进程ID// @ret: bool 操作是否成功static bool KillProcessTree(DWORD dwPID);//// @brief: DOS路径转Nt路径// @param: strPath 路径// @ret: _tstring Win32 样式的 NT 路径static _tstring DosPathToNtPath(const _tstring& strPath);//// @brief: Nt路径转DOS路径// @param: strPath 路径// @ret: _tstring DOS路径static _tstring NtPathToDosPath(const _tstring& strPath);//// @brief: 获取指定进程的PE头信息// @param: dwPID 进程ID// @param: pPEHeader PE头信息缓冲// @ret: bool 操作是否成功static bool GetPEHeader(DWORD dwPID, PE_HEADER_INFO* pPEHeader);//// @brief: 获取进程的子系统类型// @param: dwPID 进程ID// @param: dwMilliseconds 超时时间// @ret: DWORD 子系统类型// 2: IMAGE_SUBSYSTEM_WINDOWS_GUI (windows 图形用户界面 (GUI) 子系统)// 3: IMAGE_SUBSYSTEM_WINDOWS_CUI (Windows 字符模式用户界面 (CUI) 子系统)static DWORD GetSubsystemType(DWORD dwPID);//// @brief: 获取进程所运行的计算机的体系结构类型// @param: dwPID 进程ID// @ret: DWORD 计算机的体系结构类型// 0x014C: IMAGE_FILE_MACHINE_I386 (X86 平台)// 0x8664: IMAGE_FILE_MACHINE_AMD64 (X64 平台)static WORD GetMachine(DWORD dwPID);//// @brief: 进程是否为x86平台// @param: dwPID 进程ID// @ret: bool 检查结果static bool IsX86(DWORD dwPID);//// @brief: 进程是否为 X64 平台// @param: dwPID 进程ID// @ret: bool 检查结果static bool IsX64(DWORD dwPID);//// @brief: 进程是否为 ARM32 平台// @param: dwPID 进程ID// @ret: bool 检查结果static bool IsARM32(DWORD dwPID);//// @brief: 进程是否为 ARM64 平台// @param: dwPID 进程ID// @ret: bool 检查结果static bool IsARM64(DWORD dwPID);//// @brief: 进程是否运行于windows 图形用户界面 (GUI) 子系统// @param: dwPID 进程ID// @ret: bool 检查结果static bool IsWindowsGUI(DWORD dwPID);//// @brief: 进程是否运行于Windows 字符模式用户界面 (CUI) 子系统// @param: dwPID 进程ID// @ret: bool 检查结果static bool IsWindowsCUI(DWORD dwPID);private://// @brief: 获取指定进程的进程树// @param: procInfos 进程信息// @param: dwPID 进程ID// @ret: std::map<DWORD, PROC_INFO> 进程信息static PROCESS_TREE _GetProcessTree(const std::map<DWORD, PROC_INFO>& procInfos,DWORD dwPID);
};
CProcessUtils.cpp
#include "CProcessUtils.h"
#include <tlhelp32.h>
#include <psapi.h>
#include <strsafe.h>
#include <stdint.h>#define DPSAPI_VERSION = 1
#pragma comment(lib, "Psapi.lib")bool CProcessUtils::RunProcess(const _tstring& strCmd,const _tstring& strCurDir,bool bShow,bool bWait
)
{TCHAR szCommandLine[MAX_PATH] = { 0 };SECURITY_ATTRIBUTES sa = { 0 };STARTUPINFO si = { 0 };PROCESS_INFORMATION pi = { 0 };LPCTSTR lpCurrentDir = NULL;sa.bInheritHandle = TRUE;sa.lpSecurityDescriptor = NULL;sa.nLength = sizeof(sa);si.cb = sizeof(STARTUPINFO);si.dwFlags = STARTF_USESHOWWINDOW;si.wShowWindow = bShow ? SW_SHOW : SW_HIDE;si.hStdInput = NULL;si.hStdOutput = NULL;si.hStdError = NULL;if (!strCmd.empty()){::StringCchCopy(szCommandLine, _countof(szCommandLine), strCmd.c_str());}if (!strCurDir.empty()){lpCurrentDir = strCurDir.c_str();}if (!::CreateProcess(NULL, szCommandLine, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, lpCurrentDir, &si, &pi)){return false;}if (bWait){::WaitForSingleObject(pi.hProcess, INFINITE);}::CloseHandle(pi.hProcess);::CloseHandle(pi.hThread);return true;
}_tstring CProcessUtils::GetPath(DWORD dwPID, bool bNtPath)
{_tstring strPath;HANDLE hProcess = NULL;TCHAR szBuffer[MAX_PATH] = { 0 };DWORD dwSize = _countof(szBuffer);do{hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPID);if (NULL == hProcess){break;}if (0 == ::GetProcessImageFileName(hProcess, szBuffer, dwSize)){break;}if (bNtPath){strPath = DosPathToNtPath(szBuffer);}else{strPath = szBuffer;}} while (false);if (NULL != hProcess){::CloseHandle(hProcess);}return strPath;
}_tstring CProcessUtils::GetPathEx(DWORD dwPID, bool bNtPath)
{_tstring strPath;HANDLE hProcess = NULL;TCHAR szBuffer[MAX_PATH] = { 0 };DWORD dwSize = _countof(szBuffer);do{hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPID);if (NULL == hProcess){break;}if (!::QueryFullProcessImageName(hProcess, bNtPath ? 0 : PROCESS_NAME_NATIVE, szBuffer, &dwSize)){break;}strPath = szBuffer;} while (false);if (NULL != hProcess){::CloseHandle(hProcess);}return strPath;
}_tstring CProcessUtils::GetParentPath(DWORD dwPID, bool bNtPath)
{_tstring strPath;HANDLE hProcessSnap = NULL;PROCESSENTRY32 pe32 = { 0 };pe32.dwSize = sizeof(pe32);do{hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (INVALID_HANDLE_VALUE == hProcessSnap){break;}if (!::Process32First(hProcessSnap, &pe32)){break;}do{if (pe32.th32ProcessID == dwPID){strPath = GetPath(pe32.th32ParentProcessID, bNtPath);break;}} while (::Process32Next(hProcessSnap, &pe32));} while (false);if (INVALID_HANDLE_VALUE != hProcessSnap){::CloseHandle(hProcessSnap);}return strPath;
}DWORD CProcessUtils::GetParentID(DWORD dwPID)
{HANDLE hProcessSnap = NULL;PROCESSENTRY32 pe32 = { 0 };pe32.dwSize = sizeof(pe32);DWORD dwParentProcessId = 0;do{hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (INVALID_HANDLE_VALUE == hProcessSnap){break;}if (!::Process32First(hProcessSnap, &pe32)){break;}do{if (pe32.th32ProcessID == dwPID){dwParentProcessId = pe32.th32ParentProcessID;break;}} while (::Process32Next(hProcessSnap, &pe32));} while (false);if (INVALID_HANDLE_VALUE != hProcessSnap){::CloseHandle(hProcessSnap);}return dwParentProcessId;
}std::vector<_tstring> CProcessUtils::GetModules(DWORD dwPID)
{std::vector<_tstring> modulesList;TCHAR szModName[MAX_PATH] = { 0 };HMODULE* phMods = NULL;HANDLE hProcess = NULL;DWORD cbNeeded = 0;DWORD dwModSize = 0;do{hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwPID);if (NULL == hProcess){break;}if (!::EnumProcessModulesEx(hProcess, NULL, NULL, &cbNeeded, LIST_MODULES_ALL)){break;}dwModSize = cbNeeded;phMods = (HMODULE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwModSize);if (NULL == phMods){break;}if (!::EnumProcessModulesEx(hProcess, phMods, dwModSize, &cbNeeded, LIST_MODULES_ALL)){break;}size_t nModuleCnt = (cbNeeded / sizeof(HMODULE));for (size_t i = 0; i < nModuleCnt; i++){if (::GetModuleFileNameEx(hProcess, phMods[i], szModName, _countof(szModName))){modulesList.push_back(szModName);}}} while (false);if (NULL != hProcess){::CloseHandle(hProcess);}if (phMods){::HeapFree(::GetProcessHeap(), 0, phMods);}return modulesList;
}bool CProcessUtils::GetPEHeader(DWORD dwPID, PE_HEADER_INFO* pPEHeader)
{HMODULE hModule = NULL;LPVOID OldValue = NULL;BOOL isDisableWow64Fs = ::Wow64DisableWow64FsRedirection(&OldValue);bool fSuccess = false;if (nullptr == pPEHeader){return false;}do{DWORD dwFlags = LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE;hModule = ::LoadLibraryEx(GetPath(dwPID).c_str(),0,dwFlags);if (NULL == hModule){break;}LPBYTE pHeader = (BYTE*)hModule;BYTE* pImageData = (BYTE*)((ULONG_PTR)pHeader & ~((ULONG_PTR)0x03));PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pImageData;if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE){break;}PIMAGE_NT_HEADERS pNtHeader = (IMAGE_NT_HEADERS*)((BYTE*)(pDosHeader)+(DWORD)(pDosHeader->e_lfanew));if (IMAGE_NT_SIGNATURE != pNtHeader->Signature){break;}// 检查 是否为 32位程序可选头if (IMAGE_NT_OPTIONAL_HDR32_MAGIC == pNtHeader->OptionalHeader.Magic){pPEHeader->m_NtHeadersMagic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;pPEHeader->m_NtHeaders32 = *(PIMAGE_NT_HEADERS32)pNtHeader;}// 检查 是否为 64位程序可选头else if (IMAGE_NT_OPTIONAL_HDR64_MAGIC == pNtHeader->OptionalHeader.Magic){pPEHeader->m_NtHeadersMagic = IMAGE_NT_OPTIONAL_HDR64_MAGIC;pPEHeader->m_NtHeaders64 = *(PIMAGE_NT_HEADERS64)pNtHeader;}else{break;}pPEHeader->m_DosHeader = *(PIMAGE_DOS_HEADER)pImageData;fSuccess = true;} while (false);if (isDisableWow64Fs){::Wow64RevertWow64FsRedirection(OldValue);}if (NULL != hModule){::FreeLibrary(hModule);}return fSuccess;
}bool CProcessUtils::WaitForProcess(DWORD dwPID,DWORD dwMilliseconds/* = INFINITE*/
)
{HANDLE hProcess = NULL;bool fResult = false;hProcess = ::OpenProcess(SYNCHRONIZE, FALSE, dwPID);if (NULL == hProcess){return false;}fResult = (WAIT_OBJECT_0 == ::WaitForSingleObject(hProcess, dwMilliseconds));::CloseHandle(hProcess);return fResult;
}std::map<DWORD, PROC_INFO> CProcessUtils::GetAllProcessInfos()
{std::map<DWORD, PROC_INFO> infos;HANDLE hProcessSnap = NULL;PROCESSENTRY32 pe32 = { 0 };pe32.dwSize = sizeof(pe32);do{hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (INVALID_HANDLE_VALUE == hProcessSnap){break;}if (!::Process32First(hProcessSnap, &pe32)){break;}do{PROC_INFO info;info.dwParentPID = pe32.th32ParentProcessID;info.dwPID = pe32.th32ProcessID;info.strExeFile = pe32.szExeFile;info.cntThreads = pe32.cntThreads;info.nPriClassBase = pe32.pcPriClassBase;infos.insert(std::make_pair(info.dwPID, info));} while (::Process32Next(hProcessSnap, &pe32));} while (false);if (INVALID_HANDLE_VALUE != hProcessSnap){::CloseHandle(hProcessSnap);}return infos;
}std::vector<MODULE_INFO> CProcessUtils::GetModuleInfos(DWORD dwPID)
{std::vector<MODULE_INFO> vModules;HANDLE hModuleSnap = NULL;MODULEENTRY32 me32 = { 0 };me32.dwSize = sizeof(me32);do{hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32,dwPID);if (INVALID_HANDLE_VALUE == hModuleSnap){break;}if (!::Module32First(hModuleSnap, &me32)){break;}do{MODULE_INFO info;info.modBaseSize = me32.modBaseSize;info.strExePath = me32.szExePath;info.strModule = me32.szModule;info.hModule = me32.hModule;info.modBaseAddr = me32.modBaseAddr;vModules.push_back(info);} while (::Module32Next(hModuleSnap, &me32));} while (false);if (INVALID_HANDLE_VALUE != hModuleSnap){::CloseHandle(hModuleSnap);}return vModules;
}PROCESS_TREE CProcessUtils::GetProcessTree(DWORD dwPID)
{std::map<DWORD, PROC_INFO> procInfos = CProcessUtils::GetAllProcessInfos();return _GetProcessTree(procInfos, dwPID);
}PROCESS_TREE CProcessUtils::_GetProcessTree(const std::map<DWORD, PROC_INFO>& procInfos,DWORD dwPID
)
{PROCESS_TREE procTree;for (auto& item : procInfos){const PROC_INFO& info = item.second;if (item.first == dwPID){procTree.dwPID = dwPID;procTree.strExeFile = info.strExeFile;procTree.nPriClassBase = info.nPriClassBase;procTree.dwCntThreads = info.cntThreads;procTree.dwParentPID = info.dwParentPID;}else if (info.dwParentPID == dwPID){PROCESS_TREE subTree = _GetProcessTree(procInfos, info.dwPID);procTree.childProcesses.push_back(subTree);}}return procTree;
}bool CProcessUtils::KillProcess(DWORD dwPID)
{HANDLE hProcess = NULL;BOOL fSuccess = false;// 杀死进程hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwPID);if (NULL == hProcess){return false;}fSuccess = ::TerminateProcess(hProcess, 0);::CloseHandle(hProcess);return fSuccess;
}bool CProcessUtils::KillProcessTree(const PROCESS_TREE& procTree)
{HANDLE hProcess = NULL;BOOL fSuccess = false;// 杀死子进程for (auto item : procTree.childProcesses){KillProcessTree(item);}// 杀死进程hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, procTree.dwPID);if (NULL == hProcess){return false;}fSuccess = ::TerminateProcess(hProcess, 0);::CloseHandle(hProcess);return fSuccess;
}bool CProcessUtils::KillProcessTree(DWORD dwPID)
{return KillProcessTree(GetProcessTree(dwPID));
}_tstring CProcessUtils::DosPathToNtPath(const _tstring& strPath)
{_tstring strResultPath;TCHAR szDriveStrings[MAX_PATH] = { 0 };TCHAR szDosBuf[MAX_PATH] = { 0 };TCHAR szResultBuf[MAX_PATH] = { 0 };LPTSTR pDriveStr = NULL;// 获取盘符名到缓冲if (::GetLogicalDriveStrings(_countof(szDriveStrings), szDriveStrings)){// 遍历盘符名for (int i = 0; i < _countof(szDriveStrings); i += 4){pDriveStr = &szDriveStrings[i];pDriveStr[2] = _T('\0');// 查询盘符对应的DOS设备名称if (!::QueryDosDevice(pDriveStr, szDosBuf, _countof(szDosBuf))){break;}// 对比路径前缀size_t nLen = _tcslen(szDosBuf);if (0 == _tcsnicmp(strPath.c_str(), szDosBuf, nLen)){lstrcpy(szResultBuf, pDriveStr);lstrcat(szResultBuf, strPath.c_str() + nLen);strResultPath = szResultBuf;break;}}}return strResultPath;
}_tstring CProcessUtils::NtPathToDosPath(const _tstring& strPath)
{_tstring strResultPath;TCHAR szDriveStrings[MAX_PATH] = { 0 };TCHAR szDosBuf[MAX_PATH] = { 0 };TCHAR szResultBuf[MAX_PATH] = { 0 };LPTSTR pDriveStr = NULL;// 获取盘符名到缓冲if (::GetLogicalDriveStrings(_countof(szDriveStrings), szDriveStrings)){// 遍历盘符名for (int i = 0; i < _countof(szDriveStrings); i += 4){pDriveStr = &szDriveStrings[i];pDriveStr[2] = _T('\0');// 查询盘符对应的DOS设备名称if (!::QueryDosDevice(pDriveStr, szDosBuf, _countof(szDosBuf))){break;}// 对比路径前缀size_t nLen = _tcslen(pDriveStr);if (0 == _tcsnicmp(strPath.c_str(), pDriveStr, nLen)){lstrcpy(szResultBuf, szDosBuf);lstrcat(szResultBuf, strPath.c_str() + nLen);strResultPath = szResultBuf;break;}}}return strResultPath;
}DWORD CProcessUtils::GetSubsystemType(DWORD dwPID)
{PE_HEADER_INFO peHeader = { 0 };if (!GetPEHeader(dwPID, &peHeader)){return 0;}if (IMAGE_NT_OPTIONAL_HDR32_MAGIC == peHeader.m_NtHeadersMagic){return peHeader.m_NtHeaders32.OptionalHeader.Subsystem;}if (IMAGE_NT_OPTIONAL_HDR64_MAGIC == peHeader.m_NtHeadersMagic){return peHeader.m_NtHeaders64.OptionalHeader.Subsystem;}return 0;
}WORD CProcessUtils::GetMachine(DWORD dwPID)
{PE_HEADER_INFO peHeader = { 0 };if (!GetPEHeader(dwPID, &peHeader)){return 0;}if (IMAGE_NT_OPTIONAL_HDR32_MAGIC == peHeader.m_NtHeadersMagic){return peHeader.m_NtHeaders32.FileHeader.Machine;}if (IMAGE_NT_OPTIONAL_HDR64_MAGIC == peHeader.m_NtHeadersMagic){return peHeader.m_NtHeaders64.FileHeader.Machine;}return 0;
}bool CProcessUtils::IsX86(DWORD dwPID)
{return IMAGE_FILE_MACHINE_I386 == GetMachine(dwPID);
}bool CProcessUtils::IsX64(DWORD dwPID)
{return IMAGE_FILE_MACHINE_AMD64 == GetMachine(dwPID);
}bool CProcessUtils::IsARM32(DWORD dwPID)
{WORD wMachine = GetMachine(dwPID);return wMachine >= IMAGE_FILE_MACHINE_ARM && wMachine <= IMAGE_FILE_MACHINE_ARMNT;
}bool CProcessUtils::IsARM64(DWORD dwPID)
{return IMAGE_FILE_MACHINE_ARM64 == GetMachine(dwPID);
}bool CProcessUtils::IsWindowsGUI(DWORD dwPID)
{return IMAGE_SUBSYSTEM_WINDOWS_GUI == GetSubsystemType(dwPID);
}bool CProcessUtils::IsWindowsCUI(DWORD dwPID)
{return IMAGE_SUBSYSTEM_WINDOWS_CUI == GetSubsystemType(dwPID);
}
main.cpp
#include <locale.h>
#include <tchar.h>
#include "Win32Utils/CTimeUtils.h"
#include "Win32Utils/CProcessUtils.h"int _tmain(int argc, LPCTSTR argv[])
{::setlocale(LC_ALL, "");std::vector<MODULE_INFO> infos;uint64_t timeBegin = CTimeUtils::GetCurrentTickCount();uint64_t timeEnd = CTimeUtils::GetCurrentTickCount();int nRepeatCount = 100;DWORD dwPid = GetCurrentProcessId();while (true){timeBegin = CTimeUtils::GetCurrentTickCount();for (int i = 0; i < nRepeatCount; i++){//std::vector<_tstring> modList = CProcessUtils::GetModules(GetCurrentProcessId());infos = CProcessUtils::GetModuleInfos(61088);//std::vector<_tstring> modList = CProcessUtils::GetModules(61088);}timeEnd = CTimeUtils::GetCurrentTickCount();_tprintf(_T("Repeat: %d Time: %llu ms, Speed: %0.3lf/S\n"), nRepeatCount, timeEnd - timeBegin, (double)nRepeatCount * 1000 / ((double)(timeEnd - timeBegin)));system("pause");}return 0;
}