进程操作(Win32, C++)

news2024/11/16 10:36:15

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;            // 父进程ID
    DWORD       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;                  // 进程ID
    DWORD       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                  父进程的进程ID
	static 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.coloradmin.cn/o/1482614.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

element-plus表格合并

要实现这样的表格&#xff0c; 怎么做呢&#xff1f; 甚至是这种三级的呢&#xff1f; 官网的案例也是通过这个方法进行配置的&#xff0c;也就是说表格长什么样&#xff0c;关键在怎么处理的方法上。 这是官网的方法&#xff0c;可参考拓展&#xff1a; const arraySpanMeth…

SLAM ORB-SLAM2(21)基础矩阵的计算和评分

SLAM ORB-SLAM2&#xff08;21&#xff09;基础矩阵的计算和评分 1. 前言2. 基础矩阵2.1. 对级约束2.2. 推导2.3. 计算原理 3. ComputeF214. CheckFundamental 1. 前言 在 《SLAM ORB-SLAM2&#xff08;20&#xff09;查找基础矩阵》 中了解到 查找基础矩阵主要过程&#xff1…

nginx 配置浏览器不缓存文件 每次都会从服务器 请求新的文件

目录 解决问题方法说明 测试html环境js环境第一步然后修改内容 打开带有js缓存的页面强制刷新 配置nginx 每次打开页面都会重新请求index.js 文件重启nginx再次修改index.js 总结设置为全局 解决问题 适用于实时更新数据的&#xff0c;网页 可以让用户每次都是重新请求&#x…

《从0开始搭建实现apollo9.0》系列三 CANBUS模块解读

二、CANBUS代码 1、canbus模块的软件架构如下&#xff1a; 主要输入输出 输入&#xff1a;apollo::control::ControlCommand | 控制指令 输出&#xff1a; /apollo/chassis | apollo::canbus::Chassis | 车辆底盘信息接口数据&#xff0c;包括车辆速度、方向盘转角、档位、底盘…

Vue Html中插入本地视频(Video 标签)

在 Vue 中插入本地视频可以通过使用标签来实现。你可以将视频文件放在你的项目中的合适位置&#xff08;比如assets文件夹&#xff09;&#xff0c;然后在 Vue 组件中引用这个视频文件。html同理 首先&#xff0c;在你的 Vue 项目中的assets文件夹下放入你的视频文件&#xff…

兼容性比较好的浏览器推荐(2023手机浏览器排名)

浏览器在我们日常工作生活占据着重要的位置。浏览器是电脑的必备软件&#xff0c;也是手机端不可缺少的软件之一。如果你想要下载浏览器&#xff0c;却不知道哪个浏览器最好用&#xff0c;那么就看看本篇文章。下文给大家推荐2023年最热门、好用的手机浏览器&#xff0c;排行不…

计算机网络【网络安全】

计算机网络——网络安全 一、网络安全问题概述 网络安全威胁 网络安全面临两大类威胁&#xff0c;被动攻击和主动攻击 被动攻击 指攻击者从网络上窃听他人的通信内容&#xff0c;通常把这类攻击称为截获。 主动攻击 篡改 攻击者故意篡改网络上传送的报文 恶意程序 拒绝服…

java实现图片转pdf,并通过流的方式进行下载(前后端分离)

首先需要导入相关依赖&#xff0c;由于具体依赖本人也不是记得很清楚了&#xff0c;所以简短的说一下。 iText&#xff1a;PDF 操作库&#xff0c;用于创建和操作 PDF 文件。可通过 Maven 或 Gradle 引入 iText 依赖。 MultipartFile&#xff1a;Spring 框架中处理文件上传的类…

day08_分类品牌管理商品规格管理商品管理

文章目录 1 分类品牌管理1.1 菜单添加1.2 表结构介绍1.3 页面制作1.4 品牌列表加载1.4.1 后端接口BrandControllerBrandServiceBrandMapperBrandMapper.xml 1.4.2 前端对接brand.jscategoryBrand.vue 1.5 分类数据加载1.6 列表查询1.6.1 需求说明1.6.2 后端接口需求分析Categor…

软考基础知识2

1.DMA控制方式&#xff1a;直接内存存取。数据在内存与I/O设备间直接成块传送&#xff0c;不需要CPU的任何干涉&#xff0c;由DMA硬件直接执行完成。 例题&#xff1a; 2.程序计数器总是存下一个指令的地址。 例题&#xff1a; 3.可靠度的计算&#xff1a; 例题&#xff1a…

低碳策略全都有!EI论文:计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度程序代码!

适用平台&#xff1a;MatlabYalmipCplex 参考文献&#xff1a;《计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度》-电网技术 程序建立了碳交易市场下的计及电转气协同的含碳捕集与垃圾焚烧虚拟电厂优化调度模型&#xff0c;鉴于该模型具有高维非线性特点&#xff0c;求…

蓝桥杯算法题汇总

一.线性表&#xff1a;链式 例题&#xff1a;旋转链表 二.栈&#xff1a; 例题&#xff1a;行星碰撞问题 三.队列 三.数组和矩阵 例题&#xff1a;

亿道信息轻工业三防EM-T195,零售、制造、仓储一网打尽

厚度仅10.5mm&#xff0c;重量仅0.65千克的EM-T195&#xff0c;其紧凑而纤薄的设计为以往加固型平板带来了全新的轻薄概念。尽管设计时尚、轻薄&#xff0c;但经过军用认证的强固性仍然能够承受所有具有挑战性的环境条件。随身携带无负担的轻便性加上抗震功能使其成为餐厅、酒店…

Spring Initializer环境问题

1.基于jdk8与本地 环境准备 1)下载jdk8并安装 2&#xff09;下载maven 3.6.3并解压放入D盘maven目录下&#xff0c;去掉外层 设置阿里源 打开settings.xml,在mirrors标签之内增加&#xff0c;注意粘贴后</id>中的/有可能被删掉&#xff0c;要自己补上 <mirror>&l…

敏捷开发模型:一种灵活、协作和持续的软件开发方法

敏捷开发模型&#xff1a;一种灵活、协作和持续的软件开发方法 引言 在软件开发领域&#xff0c;随着市场需求的不断变化和技术的迅速发展&#xff0c;传统的瀑布模型逐渐暴露出其局限性。为了应对这些挑战&#xff0c;敏捷开发模型应运而生。敏捷开发模型强调灵活、协作和持…

Java基于springboot的厨艺交流平台的设计与实现代码

摘 要 使用旧方法对厨艺交流信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在厨艺交流信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的厨艺交流平台功…

华为HCIP Datacom H12-821 卷4

1.单选题 下面哪些策略或工具不能够应用于 OSPF: A、access-list B、prefix-list C、route- Policy D、as-path filter 正确答案&#xff1a; D 解析&#xff1a; as-path-filter命令用来创建AS路径过滤器&#xff0c;OSPF属于IGP协议&#xff0c;不涉及到AS号。 2.单选题…

AI时代,我们需要什么能力?

AI 时代&#xff0c;一定会重构很多行业&#xff0c;也会重构人民的生活工作方式&#xff0c;那么 AI 时代&#xff0c;我们需要培养什么能力呢&#xff1f; 我们应该去做那些 AI 做不了的事情&#xff01;让 AI 成为我们的工具&#xff0c;助力我们更高效的解决问题&#xff…

信息系统项目管理师--项目管理概述

开展项⽬是为了通过可交付成果达成⽬标。⽬标是所指向的结果、要取得的战略地位、要达到的⽬的、要获得的成果、要⽣产的产品或者要提供的服务。 可交付成果形成的独特并可验证的产品、成果或服务。可交付成果可能是有形的&#xff0c;也可能是⽆形的。产⽣⼀个或多个可交付成…

openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划

文章目录 openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划 openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划 完成资源负载管理功能配置前&#xff0c;需要先根据业务模型完成租户资源的规划。业…