进程操作(Win32, C++)

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;
}

7fc9a0cef6884a17a291f9710292eab0.png

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/509645.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

三位数反转问题易被忽略的两大细节

【题目描述】 输入一个三位数&#xff0c;分离出它的百位、十位和个位&#xff0c;反转后输出。 【样例输入】 127 【样例输出】 721 这个问题并不难&#xff0c;只需要两步&#xff1a; ①将这个三位数分离成三个数字&#xff08;参见“整数的分离与合成”一文&#xff…

内核中的Kconfig文件

Kconfig解析 编译内核时用于配置的Kconfig文件 以内核中的ttyprintk.c为例&#xff0c;其位于/kernel-sources/dirver/char/ttyprintk.c 如何将其编译进内核&#xff1f; 在char目录下有Kconfig文件&#xff0c;其中有如下内容 tristate 表示该模块可以选择 Y N M(以.ko形…

【物联网应用案例】从0到N,智慧农业的数据价值

智慧农业全方位渗透到农业的每一个环节&#xff0c;云端解决方案更推动了研究人员、农艺师及农民间的密切协作&#xff0c;为研发企业提供了既经济又具扩展性的完美方案。 据IDC预计&#xff0c;到2036年&#xff0c;农场收集的数据量将增加800%以上&#xff0c;这凸显了农业数…

从零开始手写RPC框架(4)

这一节主要讲述网络传输模块的代码&#xff0c;并且几乎每一行代码都加上了我个人理解的注释&#xff0c;同时也讲述了其中一些以前没见过的函数&#xff0c;和大致的底层运行逻辑。 目录 网络传输实体类网络传输实现基于Socket实现网络传输基于Netty实现网络传输客户端服务端 …

java 从环境变量中获取参数及值

window直接在这设置&#xff1a; linux在/etc/profile文件里存放&#xff1a; export keyvalue 然后立即生效&#xff1a;source /etc/profile 代码获取值这样获取&#xff1a; System.getenv("key");

windows环境下Grafana+loki+promtail入门级部署日志系统,收集Springboot(Slf4j+logback)项目日志

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 往期热门专栏回顾 专栏…

萌新学习RSA第二天(离线分解整数N)

1.yafu的使用&#xff08;离线环境分解N&#xff09;、 下载 打开 及使用 下载地址&#xff1a;https://sourceforge.net/projects/yafu/ 在下载好的并解压好的文件夹上鼠标右键打开终端 然后输入.\yafu-x64.exe并回车运行 .\yafu-x64.exe 来到这个页面就OK了 然后输入 fa…

基于Mahout实现K-Means聚类

需求分析 需要对数据集进行预处理&#xff0c;选择合适的特征进行聚类分析&#xff0c;确定聚类的数量和初始中心点&#xff0c;调用Mahout提供的K-Means算法进行聚类计算&#xff0c;评估聚类结果的准确性和稳定性。同时&#xff0c;需要对Mahout的使用和参数调优进行深入学习…

关于拖拽功能

文章目录 写在前面自己手动实现拖拽的demo技术细节&#xff1a;Js中拖拽(拉)事件&#xff08;drag 和 drop&#xff09;浏览器兼容性拖拽Api的介绍拖拽流程1.dragstart事件2.dragenter事件3.dragover事件4.drop事件(必须要dragover事件触发)5.dragend事件MDN关于拖拽的解析 相关…

STM32(6)中断

1.中断 1.1 中断的概念 STM32的中断&#xff1a; 1.2 中断优先级 用数字的大小表示中断优先级的高低&#xff0c;数字的范围&#xff1a;0000--1111&#xff08;二进制&#xff09;&#xff0c;即0-15&#xff0c;共16级优先级。 进一步对这4位二进制数进行划分&#xff0c;可…

嵌入式Qt 对话框及其类型 QDialog

一.对话框的概念 对话框是与用户进行简短交互的顶层窗口。 QDialog是Qt中所有对话框窗口的基类。 QDialog继承与QWidfet是一种容器类型的组件。 QDialog的意义&#xff1a; QDialog作为一种专业的交互窗口而存在。 QDialog不能作为子部部件嵌入其他容器中。 QDialog是定制…

基于单片机的高精度心理测试仪设计

0 前言 随着社会的不断发展,人们的物质文化生活水平也随之不断提高,但在满足个人需求的同时,心理健康问题也不断出现,且趋于更加严峻的形势。因此,做好日常的心理监测既能够将心理健康问题扼杀在源头处,又能够提醒测试者及时进行状态的调整。当前的心理测试方法众多,主要通过…