当前位置: 首页> 财经> 股票 > 南宁网站建设设计制作_宁波专业优化网站制作公司_企业营销策划方案范文_关键词seo排名

南宁网站建设设计制作_宁波专业优化网站制作公司_企业营销策划方案范文_关键词seo排名

时间:2025/8/6 17:27:29来源:https://blog.csdn.net/Flame_Cyclone/article/details/144754868 浏览次数:0次
南宁网站建设设计制作_宁波专业优化网站制作公司_企业营销策划方案范文_关键词seo排名

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;
#endifnamespace CProcessUtils
{// https://learn.microsoft.com/zh-cn/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo// 版本号结构typedef union _VERSON_NUMBER {DWORD   Data;struct {WORD wLow;      // 版本号低16位WORD wHigh;     // 版本号高16位}Version;_VERSON_NUMBER() : Data(0) {}}VERSON_NUMBER;typedef struct _VS_VER_FIXEDFILEINFO {DWORD dwSignature;                  // 0xFEEF04BDVERSON_NUMBER dwStrucVersion;       // 此结构的二进制版本号。 此成员的高序字包含主版本号,低序字包含次要版本号。VERSON_NUMBER dwFileVersionMS;      // 文件二进制版本号中最重要的 32 位。 此成员与 dwFileVersionLS 一起使用,形成用于数字比较的 64 位值。VERSON_NUMBER dwFileVersionLS;      // 文件二进制版本号中最低有效 32 位。 此成员与 dwFileVersionMS 一起使用,形成用于数字比较的 64 位值。VERSON_NUMBER dwProductVersionMS;   // 分发此文件的产品的二进制版本号中最重要的 32 位。 此成员与 dwProductVersionLS 一起使用,形成用于数字比较的 64 位值。VERSON_NUMBER dwProductVersionLS;   // 分发此文件的产品的二进制版本号中最低有效 32 位。 此成员与 dwProductVersionMS 一起使用,形成用于数字比较的 64 位值。DWORD dwFileFlagsMask;              // 包含指定 dwFileFlags 中的有效位的位掩码。 仅当在创建文件时定义位时,位才有效。struct {DWORD fVS_FF_DEBUG : 1;             // 该文件包含调试信息,或者在启用调试功能的情况下进行编译。DWORD fVS_FF_PRERELEASE : 1;        // 该文件是开发版本,而不是商业发布的产品。DWORD fVS_FF_PRIVATEBUILD : 1;      // 文件不是使用标准发布过程生成的。 如果设置了此标志, StringFileInfo 结构应包含 PrivateBuild 条目。DWORD fVS_FF_PATCHED : 1;           // 该文件已修改,与同一版本号的原始发货文件不同。DWORD fVS_FF_INFOINFERRED : 1;      // 文件的版本结构是动态创建的;因此,此结构中的某些成员可能为空或不正确。 切勿在文件的 VS_VERSIONINFO 数据中设置此标志。DWORD fVS_FF_SPECIALBUILD : 1;      // 该文件由原始公司使用标准发布过程生成,但是相同版本号的正常文件的变体。 如果设置了此标志, StringFileInfo 结构应包含 SpecialBuild 条目。DWORD fVS_FF_Reserved : 26;         // 保留未使用}dwFileFlags;   // 包含指定文件的布尔属性的位掩码。union _FILE_OS {DWORD dwData;struct {enum eFileOSLo : WORD {eVOS_LO_UNKNOWN = 0x0000L,  // 系统不知道设计该文件的操作系统eVOS_LO_WINDOWS16 = 0x0001L,  // 该文件是为 16 位 Windows 设计的eVOS_LO_PM16 = 0x0002L,  // 该文件是为 16 位 Presentation Manager 设计的eVOS_LO_PM32 = 0x0003L,  // 该文件是为 32 位 Presentation Manager 设计的eVOS_LO_WINDOWS32 = 0x0004L,  // 该文件专为 32 位 Windows 设计}Low;enum eFileOSHi : WORD {eVOS_HI_UNKNOWN = 0x0000L,  // 系统不知道设计该文件的操作系统eVOS_HI_DOS = 0x0001L,  // 该文件是针对 MS-DOS 设计的eVOS_HI_OS216 = 0x0002L,  // 该文件是为 16 位 OS/2 设计的eVOS_HI_OS232 = 0x0003L,  // 该文件是为 32 位 OS/2 设计的eVOS_HI_NT = 0x0004L,  // 该文件是为 Windows NT 设计的}High;};}dwFileOS;      // 为其设计此文件的操作系统enum eFileType : DWORD {eVFT_UNKNOWN = 0x00000000L,  // 系统不知道文件类型eVFT_APP = 0x00000001L,  // 该文件包含一个应用程序eVFT_DLL = 0x00000002L,  // 该文件包含一个 DLLeVFT_DRV = 0x00000003L,  // 该文件包含设备驱动程序eVFT_FONT = 0x00000004L,  // 该文件包含字体eVFT_VXD = 0x00000005L,  // 该文件包含一个虚拟设备eVFT_STATIC_LIB = 0x00000007L   // 该文件包含一个静态链接库}dwFileType;    // 文件的常规类型union {// 如果 dwFileTypeVFT_FONT, 则 dwFileSubtype 可以是以下值之一。enum eFileSubtypeDrv : DWORD {eVFT2_DRV_UNKNOWN = 0x00000000L,  //系统未知驱动程序类型。eVFT2_DRV_PRINTER = 0x00000001L,  //文件包含打印机驱动程序。eVFT2_DRV_KEYBOARD = 0x00000002L,  //文件包含键盘驱动程序。eVFT2_DRV_LANGUAGE = 0x00000003L,  //文件包含语言驱动程序。eVFT2_DRV_DISPLAY = 0x00000004L,  //文件包含显示驱动程序。eVFT2_DRV_MOUSE = 0x00000005L,  //文件包含鼠标驱动程序。eVFT2_DRV_NETWORK = 0x00000006L,  //文件包含网络驱动程序。eVFT2_DRV_SYSTEM = 0x00000007L,  //文件包含系统驱动程序。eVFT2_DRV_INSTALLABLE = 0x00000008L,  //文件包含可安装的驱动程序。eVFT2_DRV_SOUND = 0x00000009L,  //该文件包含声音驱动程序。eVFT2_DRV_COMM = 0x0000000AL,  //文件包含通信驱动程序。eVFT2_DRV_VERSIONED_PRINTER = 0x0000000CL,  //文件包含版本控制打印机驱动程序。}dwFileTypeVFT_DRV;     // 驱动文件类型// 如果 dwFileTypeVFT_VXD, 则 dwFileSubtype 包含虚拟设备控制块中包含的虚拟设备标识符。enum eFileSubtypeFont : DWORD {eVFT2_FONT_UNKNOWN = 0x00000000L,  //系统未知字体类型。eVFT2_FONT_RASTER = 0x00000001L,  //文件包含光栅字体。eVFT2_FONT_TRUETYPE = 0x00000003L,  //文件包含 TrueType 字体。eVFT2_FONT_VECTOR = 0x00000002L,  //文件包含矢量字体。}dwFileTypeVFT_FONT;    // 字体文件类型}dwFileSubtype;     // 文件的子类型DWORD dwFileDateMS; // 文件的 64 位二进制创建日期和时间戳中最高有效 32 位。DWORD dwFileDateLS; // 文件的 64 位二进制创建日期和时间戳的最低有效 32 位。} VS_VER_FIXEDFILEINFO, * PVS_VER_FIXEDFILEINFO;// 语言与代码页typedef struct _LANGANDCODEPAGE {WORD wLanguage;WORD wCodePage; // https://learn.microsoft.com/zh-cn/windows/win32/menurc/varfileinfo-block_LANGANDCODEPAGE() : wLanguage(0), wCodePage(0) {}bool operator < (const _LANGANDCODEPAGE& r) const{MAKELANGID(this->wLanguage, this->wCodePage);if (this->wLanguage < r.wLanguage){return true;}if (this->wCodePage < r.wCodePage){return true;}return false;}bool operator == (const _LANGANDCODEPAGE& r) const{return this->wLanguage == r.wLanguage && this->wCodePage == r.wCodePage;}}LANGANDCODEPAGE, * PLANGANDCODEPAGE;// 版本号辅助类class CVersionNumber{public:CVersionNumber();CVersionNumber(const _tstring& strVer);CVersionNumber(WORD v1, WORD v2, WORD v3, WORD v4);CVersionNumber& operator = (const _tstring& strVer);_tstring GetString() const;bool IsEmpty() const;void Clear();bool operator == (const CVersionNumber& ref);bool operator != (const CVersionNumber& ref);bool operator < (const CVersionNumber& ref);bool operator <= (const CVersionNumber& ref);bool operator > (const CVersionNumber& ref);bool operator >= (const CVersionNumber& ref);private:int _Compare(const CVersionNumber& ref) const;private:WORD m_nVer[4];         //版本号};// PE文件信息typedef struct _VERSION_INFO{LANGANDCODEPAGE langAndCodePage;            // 语言代码页_tstring strLanguageName;                   // 语言名_tstring strComments;                       // 文件注释_tstring strInternalName;                   // 内部名称_tstring strProductName;                    // 产品名称_tstring strCompanyName;                    // 公司名称_tstring strLegalCopyright;                 // 法律版权_tstring strProductVersion;                 // 产品版本_tstring strFileDescription;                // 文件描述_tstring strLegalTrademarks;                // 合法商标_tstring strPrivateBuild;                   // 私有构建_tstring strFileVersion;                    // 文件版本_tstring strOriginalFilename;               // 原始文件名_tstring strSpecialBuild;                   // 特殊构建_tstring strFileVersionEx;                  // 文件版本(从 VS_FIXEDFILEINFO 中获取)_tstring strProductVersionEx;               // 产品版本(从 VS_FIXEDFILEINFO 中获取)VS_VER_FIXEDFILEINFO vsFixedInfo;           // 固定文件信息CVersionNumber FileVerNumber;               // 文件版本号CVersionNumber ProductVerNumber;            // 产品版本号}VERSION_INFO;using VERSION_LIST = std::map<LANGANDCODEPAGE, VERSION_INFO>;// 进程信息typedef struct _PROC_INFO{_tstring        strFilePath;            // 可执行文件的名称_tstring        strExeFile;             // 可执行文件的名称_tstring        strDomainName;          // 域名_tstring        strUserName;            // 用户名LONG            nPriClassBase;          // 此进程创建的任何线程的基本优先级DWORD           dwPID;                  // 进程IDDWORD           dwParentPID;            // 父进程IDDWORD           cntThreads;             // 进程启动的执行线程DWORD           dwGdiCount;             // GDI对象计数DWORD           dwUserCount;            // 用户对象计数DWORD           dwHandleCount;          // 句柄计数DWORD           dwSessionId;            // 会话IDBOOL            fWow64;                 // 32位应用程序VERSION_LIST    fileVersion;            // 文件版本信息_PROC_INFO():dwPID(0),dwParentPID(0),nPriClassBase(0),cntThreads(0),dwGdiCount(0),dwUserCount(0),dwHandleCount(0),dwSessionId(0),fWow64(0){}}PROC_INFO;// 模块信息typedef struct _MODULE_INFO{_tstring    strModule;              // 模块名_tstring    strExePath;             // 模块路径DWORD   th32ProcessID;              // 要检查其模块的进程标识符DWORD   GlblcntUsage;               // 模块的负载计数,通常没有意义,通常等于0xFFFFBYTE* modBaseAddr;                // 拥有进程上下文中模块的基址DWORD   modBaseSize;                // 模块的大小(以字节为单位)HMODULE hModule;                    // 拥有进程上下文中模块的句柄_MODULE_INFO():th32ProcessID(0),GlblcntUsage(0),modBaseAddr(0),modBaseSize(0),hModule(NULL){}}MODULE_INFO;// 进程节点信息typedef struct _PROC_NODE{PROC_INFO   ProcInfo;               // 进程信息std::vector<_PROC_NODE> NodeList;   // 子进程列表}PROC_NODE;// PE文件头信息typedef struct _PE_HEADER_INFO{IMAGE_DOS_HEADER    m_DosHeader;            // Dos头union {IMAGE_NT_HEADERS64  m_NtHeaders64;          // NT头(64位)IMAGE_NT_HEADERS32  m_NtHeaders32;          // NT头(32位)};WORD                m_NtHeadersMagic;       // NT头魔数}PE_HEADER_INFO;// 进程名信息typedef struct _PROCESS_NAME_INFO{DWORD SessionId;DWORD ProcessId;_tstring ProcessName;_tstring UserName;_tstring DomainName;} PROCESS_NAME_INFO, * PPROCESS_NAME_INFO;// 进程组信息typedef struct _PROCESS_GROUPS_INFO{_tstring DomainName;_tstring UserName;_tstring SID;DWORD Attributes;} PROCESS_GROUPS_INFO, * PPROCESS_GROUPS_INFO;// 窗口信息typedef struct _WND_INFO{HWND hWnd;DWORD dwPid;DWORD dwTid;_tstring strClass;_tstring strText;}WND_INFO;// 窗口节点信息typedef struct _WND_NODE{HWND hWnd;                          // 窗口句柄DWORD dwPid;                        // 窗口进程IDDWORD dwTid;                        // 窗口线程ID_tstring strClass;                  // 窗口类名_tstring strText;                   // 窗口名_tstring strModule;                 // 窗口关联的模块名std::vector<_WND_NODE> NodeList;    // 子窗口列表}WND_NODE;using PROC_NAME_LIST = std::map<DWORD, PROCESS_NAME_INFO>;using PROC_INFO_LIST = std::map<DWORD, PROC_INFO>;using PROC_NODE_LIST = std::map<DWORD, PROC_NODE>;using MODULE_INFO_LIST = std::vector<MODULE_INFO>;//// 进程提权// @param: hProcess             进程句柄// @param: lpPrivilegesName     特权名// @ret: bool                   操作是否成功bool EnablePrivileges(HANDLE hProcess, LPCTSTR lpPrivilegesName);//// @brief: 创建进程// @param: strExePath           可执行文件路径// @param: strCommand           命令参数// @param: strCurDir            程序的当前目录// @param: bShow                是否显示程序// @param: bWait                是否等待程序直到其退出// @ret: bool                   操作是否成功bool CreateProcessNormal(const _tstring& strExePath = _T(""),const _tstring& strCommand = _T(""),const _tstring& strCurDir = _T(""),bool bShow = true,bool bWait = true);//// @brief: 创建 带有UI 权限的进程// @param: strExePath           可执行文件路径// @param: strCommand           命令参数// @param: strCurDir            程序的当前目录DWORD CreateProcessWithUIAccess(const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir = _T(""));//// @brief: 创建不带UI权限的进程// @param: strExePath           可执行文件路径// @param: strCommand           命令参数// @param: strCurDir            程序的当前目录DWORD CreateProcessNoUIAccess(const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir = _T(""));//// @brief: 创建 SYSTEM 权限的进程// @param: strExePath           可执行文件路径// @param: strCommand           命令参数// @param: strCurDir            程序的当前目录bool CreateProcessWithSystem(const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir = _T(""));//// @brief: 检查指定进程是否有UI权限// @param: dwPid                进程ID// @param: pdwErr               输出错误码// @param: pfUIAccess           输出权限// @param: 操作是否成功BOOL CheckProcessUIAccess(DWORD dwPid,DWORD* pdwErr,DWORD* pfUIAccess);//// @brief: 获取文件版本列表// @param: strFile              文件路径// @param: fLocalised           本地化// @ret: VERSION_LIST           文件版本信息列表VERSION_LIST GetFileVersionList(const _tstring& strFile, bool fLocalised = true);//// @brief: 获取文件版本// @param: strFile              文件路径// @param: fLocalised           本地化// @ret: VERSION_INFO           文件版本信息VERSION_INFO GetFileVersion(const _tstring& strFile, bool fLocalised = true);//// @brief: 获取进程可执行文件路径// @param: dwPID                进程ID// @param: bNtPath              是否为Win32 样式的 NT 路径// @ret: _tstring               进程可执行文件路径_tstring GetPath(DWORD dwPID, bool bNtPath = true);//// @brief: 获取进程可执行文件路径// @param: dwPID                进程ID// @param: bNtPath              是否为Win32 样式的 NT 路径// @ret: _tstring               进程可执行文件路径_tstring GetPathEx(DWORD dwPID, bool bNtPath = true);//// @brief: 获取父进程可执行文件路径// @param: dwPID                进程ID// @param: bNtPath              是否为Win32 样式的 NT 路径// @ret: _tstring               进程可执行文件路径_tstring GetParentPath(DWORD dwPID, bool bNtPath = true);//// @brief: 获取进程名列表// @ret: PROC_NAME_LIST         进程名列表PROC_NAME_LIST GetProcessNames();//// @brief: 获取进程信息列表// @param: strName              进程名// @param: dwPID                进程ID// @ret: std::map<DWORD, PROC_INFO>  进程信息列表PROC_INFO_LIST GetProcessInfos(const _tstring& strName = _T(""), DWORD dwPID = 0);//// @brief: 获取进程信息// @param: dwPID                进程ID// @ret: PROC_INFO              进程信息PROC_INFO GetProcessInfo(DWORD dwPID);//// @brief: 获取所有进程节点// @ret: PROC_NODE_LIST  进程节点信息PROC_NODE_LIST GetProcessNodes();//// @brief: 获取指定进程的模块信息(注意: 32位进程不能获取64位进程的模块信息)// @param: dwPID                进程ID// @ret: MODULE_INFO_LIST       模块信息MODULE_INFO_LIST GetModuleInfos(DWORD dwPID);//// @brief: 获取进程加载的模块列表(注意: 32位进程不能获取64位进程的模块信息)// @param: dwPID                进程ID// @ret: _tstring               模块列表std::vector<_tstring> GetModules(DWORD dwPID);//// @brief: 获取指定进程的进程节点// @ret: std::map<DWORD, PROC_INFO>  进程信息PROC_NODE GetProcessNode(DWORD dwPID);//// @brief: 获取父进程的进程ID// @param: dwPID                进程ID// @ret: DWORD                  父进程的进程IDDWORD GetParentID(DWORD dwPID);//// @brief: 等待进程结束// @param: dwPID                进程ID// @param: dwMilliseconds       超时时间// @ret: bool                   操作是否成功bool WaitForProcess(DWORD dwPID, DWORD dwMilliseconds = INFINITE);//// @brief: 杀死指定进程// @param: strName              进程名// @ret: bool                   操作是否成功bool KillProcess(const _tstring& strName = _T(""));//// @brief: 杀死指定进程// @param: dwPID                进程ID// @ret: bool                   操作是否成功bool KillProcess(DWORD dwPID);//// @brief: 杀死指定进程ID的进程节点// @param: dwPID                进程ID// @ret: bool                   操作是否成功bool KillProcessNode(DWORD dwPID);//// @brief: DOS路径转Nt路径// @param: strPath              路径// @ret: _tstring               Win32 样式的 NT 路径_tstring DosPathToNtPath(const _tstring& strPath);//// @brief: Nt路径转DOS路径// @param: strPath              路径// @ret: _tstring               DOS路径_tstring NtPathToDosPath(const _tstring& strPath);//// @brief: 获取指定进程的PE头信息// @param: dwPID                进程ID// @param: pPEHeader            PE头信息缓冲// @ret: bool                   操作是否成功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) 子系统)DWORD GetSubsystemType(DWORD dwPID);//// @brief: 指定进程是否为 64 位处理器上运行的 32 位应用程序// @param: dwPID                进程ID// @param: dwMilliseconds       超时时间// @ret: bool                   进程是否为 64 位处理器上运行的 32 位应用程序bool IsWow64Process(DWORD dwPID);//// @brief: 指定进程是否 32 位应用程序// @param: dwPID                进程ID// @param: dwMilliseconds       超时时间// @ret: bool                   进程是否 32 位应用程序bool IsProcessX86(DWORD dwPID);//// @brief: 指定进程是否 64 位应用程序// @param: dwPID                进程ID// @param: dwMilliseconds       超时时间// @ret: bool                   进程是否 64 位应用程序bool IsProcessX64(DWORD dwPID);//// @brief: 获取进程所运行的计算机的体系结构类型// @param: dwPID                进程ID// @ret: DWORD                  计算机的体系结构类型//                              0x014C: IMAGE_FILE_MACHINE_I386 (X86 平台)//                              0x8664: IMAGE_FILE_MACHINE_AMD64 (X64 平台)WORD GetMachine(DWORD dwPID);//// @brief: 进程是否为x86平台// @param: dwPID                进程ID// @ret: bool                   检查结果bool IsX86(DWORD dwPID);//// @brief: 进程是否为 X64 平台// @param: dwPID                进程ID// @ret: bool                   检查结果bool IsX64(DWORD dwPID);//// @brief: 进程是否为 ARM32 平台// @param: dwPID                进程ID// @ret: bool                   检查结果bool IsARM32(DWORD dwPID);//// @brief: 进程是否为 ARM64 平台// @param: dwPID                进程ID// @ret: bool                   检查结果bool IsARM64(DWORD dwPID);//// @brief: 进程是否运行于 windows 图形用户界面 (GUI) 子系统// @param: dwPID                进程ID// @ret: bool                   检查结果bool IsWindowsGUI(DWORD dwPID);//// @brief: 进程是否运行于Windows 字符模式用户界面 (CUI) 子系统// @param: dwPID                进程ID// @ret: bool                   检查结果bool IsWindowsCUI(DWORD dwPID);//// @brief: 挂起进程// @param: dwPID                进程ID// @ret: bool                   检查结果bool SuspendProcess(DWORD dwPID);//// @brief: 挂起进程节点// @param: dwPID                进程ID// @ret: bool                   检查结果bool SuspendProcessNode(DWORD dwPID);//// @brief: 恢复进程// @param: dwPID                进程ID// @ret: bool                   检查结果bool ResumeProcess(DWORD dwPID);//// @brief: 恢复进程节点// @param: dwPID                进程ID// @ret: bool                   检查结果bool ResumeProcessNode(DWORD dwPID);//// @brief: 获取进程组信息// @param: dwPID                进程ID// @ret: std::vector<PROCESS_GROUPS_INFO>       进程组信息std::vector<PROCESS_GROUPS_INFO> GetProcessGroupsInfo(DWORD dwPID);//// @brief: 获取进程中句柄计数// @param: dwPID                进程ID// @ret: DWORD                  句柄计数DWORD GetProcessHandleCount(DWORD dwPID);//// @brief: 获取进程窗口列表// @param: dwPID                进程ID// @ret: std::map<HWND, WND_INFO>                  窗口列表std::map<HWND, WND_INFO> GetProcessWindows(DWORD dwPid);//// @brief: 获取进程窗口节点列表// @param: dwPID                进程ID// @ret: std::map<HWND, WND_NODE>                  窗口节点列表std::map<HWND, WND_NODE> GetProcessWindowNodes(DWORD dwPid);//// 创建UI权限令牌// @param: phToken              输出令牌缓冲// @ret: DWORD                  错误码DWORD _CreateUIAccessToken(PHANDLE phToken);//// 创建指定进程的令牌// @param: pid                  进程ID// @param: strExePath           可执行文件路径// @param: strCommand           命令参数// @param: strCurDir            程序的当前目录// @ret: bool                   是否操作成功bool CreateProcessWithPidToken(DWORD pid,const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir);
}

CProcessUtils.cpp

#include "CProcessUtils.h"
#include <tlhelp32.h>
#include <psapi.h>
#include <strsafe.h>
#include <stdint.h>
#include <WtsApi32.h>
#include <sddl.h>#pragma comment(lib, "Wtsapi32.lib" )
#pragma comment(lib, "Advapi32.lib" )
#pragma comment(lib, "Version.lib")#define NT_SUCCESS(Status)  (((NTSTATUS)(Status)) >= 0)
#define STATUS_SUCCESS  ((NTSTATUS)0x00000000L)#define DPSAPI_VERSION = 1
#pragma comment(lib, "Psapi.lib")namespace CProcessUtils
{CVersionNumber::CVersionNumber():m_nVer{ 0 }{};CVersionNumber::CVersionNumber(const _tstring& strVer):m_nVer{ 0 }{_stscanf_s(strVer.c_str(), _T("%hd.%hd.%hd.%hd"), &m_nVer[0], &m_nVer[1], &m_nVer[2], &m_nVer[3]);}CVersionNumber::CVersionNumber(WORD v1, WORD v2, WORD v3, WORD v4):m_nVer{ v1, v2, v3, v4 }{}CVersionNumber& CVersionNumber::operator = (const _tstring& strVer){_stscanf_s(strVer.c_str(), _T("%hd.%hd.%hd.%hd"), &m_nVer[0], &m_nVer[1], &m_nVer[2], &m_nVer[3]);return *this;}int CVersionNumber::_Compare(const CVersionNumber& ref) const{for (int i = 0; i < _countof(m_nVer); i++){if (m_nVer[i] != ref.m_nVer[i]){return (m_nVer[i] > ref.m_nVer[i] ? 1 : -1);}}return 0;}_tstring CVersionNumber::GetString() const{TCHAR szBuf[MAX_PATH] = { 0 };(void)::StringCchPrintf(szBuf, _countof(szBuf), _T("%hd.%hd.%hd.%hd"),m_nVer[0],m_nVer[1],m_nVer[2],m_nVer[3]);return szBuf;}bool CVersionNumber::IsEmpty() const{for (const auto& item : m_nVer){if (0 != item){return false;}}return true;}void CVersionNumber::Clear(){for (auto& item : m_nVer){item = 0;}}bool CVersionNumber::operator == (const CVersionNumber& ref){return _Compare(ref) == 0;}bool CVersionNumber::operator != (const CVersionNumber& ref){return _Compare(ref) != 0;}bool CVersionNumber::operator < (const CVersionNumber& ref){return _Compare(ref) < 0;}bool CVersionNumber::operator <= (const CVersionNumber& ref){return _Compare(ref) <= 0;}bool CVersionNumber::operator > (const CVersionNumber& ref){return _Compare(ref) > 0;}bool CVersionNumber::operator >= (const CVersionNumber& ref){return _Compare(ref) >= 0;}//// @brief: 杀死进程节点// @param: procNode             进程节点// @ret: bool                   操作是否成功bool _KillProcessNode(const PROC_NODE& procNode);//// @brief: 挂起进程节点// @param: procNode             进程节点// @ret: bool                   检查结果bool _SuspendProcessNode(const PROC_NODE& procNode);//// @brief: 恢复进程节点// @param: procNode             进程节点// @ret: bool                   检查结果bool _ResumeProcessNode(const PROC_NODE& procNode);//// @brief: 获取指定进程的进程节点// @param: procInfos            进程信息// @param: dwPID                进程ID// @ret: PROC_LIST  进程信息PROC_NODE _GetProcessNode(const PROC_INFO_LIST& procInfos,DWORD dwPID);//// @brief: 复制指定进程名的令牌// @param: strName              进程名// @param: dwSessionId          会话ID// @param: dwDesiredAccess      权限// @param: phToken              输出令牌缓冲// @ret: DWORD                  操作结果错误码DWORD _DuplicateProcessToken(const _tstring& strName,DWORD dwSessionId,DWORD dwDesiredAccess,PHANDLE phToken);// @brief: 创建带有UI权限的进程// @param: strExePath           可执行文件路径// @param: strCommand           命令参数// @param: strCurDir            程序的当前目录// @param: fUIAccess            是否带有UI权限// @ret: DWORD                  操作结果错误码DWORD _CreateProcessWithUIAccess(const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir = _T(""),bool fUIAccess = true);// 多字节字符串转宽字节字符串std::wstring _MultiStrToWStr(UINT CodePage, const std::string& str);// 字符串转宽字节字符串std::wstring _TStrToWStr(const _tstring& str);// 枚举进程窗口void _EnumProcessWindows(std::map<HWND, WND_INFO>& infos, HWND hWnd, DWORD dwPid);// 获取子窗口节点WND_NODE _GetWindowNode(HWND hWnd, std::vector<MODULE_INFO>& modules);std::wstring _MultiStrToWStr(UINT CodePage,const std::string& str){//计算缓冲区所需的字符长度int cchWideChar = ::MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, NULL);std::wstring strResult(cchWideChar, 0);//成功则返回写入到指示的缓冲区的字符数size_t nConverted = ::MultiByteToWideChar(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size());//调整内容长度strResult.resize(nConverted);return strResult;}std::wstring _TStrToWStr(const _tstring& str){
#ifdef _UNICODEreturn str;
#elsereturn _MultiStrToWStr(CP_ACP, str);
#endif}bool EnablePrivileges(HANDLE hProcess,LPCTSTR lpPrivilegesName){HANDLE hToken = NULL;LUID luidValue = { 0 };TOKEN_PRIVILEGES tokenPrivileges = { 0 };BOOL isSuccess = FALSE;do{if (!::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)){break;}if (!::LookupPrivilegeValue(NULL, lpPrivilegesName, &luidValue)){break;}tokenPrivileges.PrivilegeCount = 1;tokenPrivileges.Privileges[0].Luid = luidValue;tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;if (!::AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 0, NULL, NULL)){break;}isSuccess = true;} while (false);if (hToken){::CloseHandle(hToken);}return isSuccess;}// 操作系统 版本号// Windows 11               10.0*// Windows 10               10.0*// Windows Server 2022      10.0*// Windows Server 2019      10.0*// Windows Server 2016      10.0*// Windows 8.1              6.3*// Windows Server 2012 R2   6.3*// Windows 8                6.2// Windows Server 2012      6.2// Windows 7                6.1// Windows Server 2008 R2   6.1// Windows Server 2008      6.0// Windows Vista            6.0// Windows Server 2003 R2   5.2// Windows Server 2003      5.2// Windows XP 64 位版本     5.2// Windows XP               5.1// Windows 2000             5.0static bool _GetNtVersionNumbers(DWORD* pMajor, DWORD* pMinor, DWORD* pBuild){typedef VOID(NTAPI* NTPROC)(DWORD* dwMajor, DWORD* dwMinor, DWORD* dwBuild);HMODULE hModule = NULL;static NTPROC ProcAddress = NULL;bool fResult = false;if (NULL == ProcAddress){hModule = ::LoadLibrary(_T("ntdll.dll"));if (NULL != hModule){ProcAddress = (NTPROC)::GetProcAddress(hModule, "RtlGetNtVersionNumbers");}}if (NULL != ProcAddress){fResult = true;ProcAddress(pMajor, pMinor, pBuild);*pBuild &= 0xffff;}if (NULL != hModule){::FreeLibrary(hModule);}return fResult;}static bool IsWindowsXPOrServer2003(){DWORD dwMajor = 0;DWORD dwMinor = 0;DWORD dwBuild = 0;if (!_GetNtVersionNumbers(&dwMajor, &dwMinor, &dwBuild)){return false;}if (dwMajor == 5 && dwMinor >= 1){return true;}return false;}static DWORD GetQueryAccess(){static DWORD dwDesiredAccess = PROCESS_QUERY_LIMITED_INFORMATION;if (0 != dwDesiredAccess){return dwDesiredAccess;}if (IsWindowsXPOrServer2003()){dwDesiredAccess = PROCESS_QUERY_INFORMATION;}return dwDesiredAccess;}bool CreateProcessNormal(const _tstring& strExePath/* = _T("")*/,const _tstring& strCommand/* = _T("")*/,const _tstring& strCurDir/* = _T("")*/,bool bShow,bool bWait){SECURITY_ATTRIBUTES   sa = { 0 };STARTUPINFO si = { 0 };PROCESS_INFORMATION pi = { 0 };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;_tstring exePath = strExePath;_tstring exeCommand = strCommand;_tstring exeCurDir = strCurDir;LPCTSTR lpApplicationName = NULL;LPTSTR lpCommandLine = NULL;LPCTSTR lpCurrentDir = NULL;if (!exePath.empty()){lpApplicationName = exePath.c_str();}if (!exeCommand.empty()){lpCommandLine = (LPTSTR)exeCommand.c_str();}if (!exeCurDir.empty()){lpCurrentDir = exeCurDir.c_str();}if (!::CreateProcess(lpApplicationName, lpCommandLine, 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 GetPath(DWORD dwPID, bool bNtPath){_tstring strPath;HANDLE hProcess = NULL;TCHAR szBuffer[MAX_PATH] = { 0 };DWORD dwSize = _countof(szBuffer);do{hProcess = ::OpenProcess(GetQueryAccess(), FALSE, dwPID);if (NULL == hProcess){break;}// 句柄必须具有 PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION 访问权限。// Windows Server 2003 和 Windows XP: 句柄必须具有 PROCESS_QUERY_INFORMATION 访问权限。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 GetPathEx(DWORD dwPID, bool bNtPath){_tstring strPath;HANDLE hProcess = NULL;TCHAR szBuffer[MAX_PATH] = { 0 };DWORD dwSize = _countof(szBuffer);do{hProcess = ::OpenProcess(GetQueryAccess(), FALSE, dwPID);if (NULL == hProcess){break;}// 最低受支持的客户端: Windows Vista [仅限桌面应用]// 最低受支持的服务器: Windows Server 2008 [仅限桌面应用]// 进程句柄权限: PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATIONif (!::QueryFullProcessImageName(hProcess, bNtPath ? 0 : PROCESS_NAME_NATIVE, szBuffer, &dwSize)){break;}strPath = szBuffer;} while (false);if (NULL != hProcess){::CloseHandle(hProcess);}return strPath;}_tstring 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 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> 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 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 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;}PROC_NAME_LIST GetProcessNames(){PROC_NAME_LIST mapResult;PWTS_PROCESS_INFO pPi = NULL;DWORD dwCount = 0;do{if (!::WTSEnumerateProcesses(NULL, 0, 1, &pPi, &dwCount)){break;}for (DWORD i = 0; i < dwCount; i++){PSID pUserSid = pPi[i].pUserSid;TCHAR szName[MAX_PATH] = { 0 };DWORD cchName = _countof(szName);TCHAR szDomainName[MAX_PATH] = { 0 };DWORD cchDomainName = _countof(szDomainName);SID_NAME_USE sidNameUse = SidTypeUser;if (::LookupAccountSid(NULL, pUserSid, szName, &cchName, szDomainName, &cchDomainName, &sidNameUse)){}PROCESS_NAME_INFO info;info.SessionId = pPi[i].SessionId;info.ProcessName = pPi[i].pProcessName;info.ProcessId = pPi[i].ProcessId;info.UserName = szName;info.DomainName = szDomainName;mapResult.insert(std::make_pair(pPi[i].ProcessId, info));}} while (false);if (pPi){::WTSFreeMemory(pPi);}return mapResult;}PROC_INFO_LIST GetProcessInfos(const _tstring& strName/* = _T("")*/, DWORD dwPID/* = 0*/){PROC_INFO_LIST infos;HANDLE hProcessSnap = NULL;PROCESSENTRY32 pe32 = { 0 };pe32.dwSize = sizeof(pe32);DWORD dwQueryAccess = GetQueryAccess();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;HANDLE hProcess = NULL;DWORD dwHandleCount = 0;DWORD dwGdiCount = 0;DWORD dwUserCount = 0;// 获取句柄数量, GUI对象数量, 用户对象数量do{// 打开进程hProcess = ::OpenProcess(dwQueryAccess, FALSE, info.dwPID);if (NULL == hProcess){break;}::GetProcessHandleCount(hProcess, &dwHandleCount);dwGdiCount = GetGuiResources(hProcess, GR_GDIOBJECTS);dwUserCount = GetGuiResources(hProcess, GR_USEROBJECTS);BOOL Wow64Process = FALSE;if (::IsWow64Process(hProcess, &Wow64Process)){info.fWow64 = Wow64Process;}} while (false);if (NULL != hProcess){::CloseHandle(hProcess);}// 进程 ID 筛选if (0 == dwPID || dwPID == info.dwPID){if (strName.empty() || 0 == _tcsicmp(strName.c_str(), pe32.szExeFile)){info.dwHandleCount = dwHandleCount;info.dwGdiCount = dwGdiCount;info.dwUserCount = dwUserCount;info.strFilePath = GetPath(info.dwPID);info.fileVersion = GetFileVersionList(info.strFilePath);infos.insert(std::make_pair(info.dwPID, info));}}} while (::Process32Next(hProcessSnap, &pe32));} while (false);if (INVALID_HANDLE_VALUE != hProcessSnap){::CloseHandle(hProcessSnap);}// 获取进程用户名信息PROC_NAME_LIST mapResult = GetProcessNames();for (auto& item : infos){auto itFind = mapResult.find(item.first);if (mapResult.end() != itFind){item.second.strDomainName = itFind->second.DomainName;item.second.strUserName = itFind->second.UserName;item.second.dwSessionId = itFind->second.SessionId;}}return infos;}PROC_INFO GetProcessInfo(DWORD dwPID){PROC_INFO info;PROC_INFO_LIST infos = GetProcessInfos(_T(""), dwPID);auto itFind = infos.find(dwPID);if (itFind != infos.end()){info = itFind->second;}return info;}PROC_NODE_LIST GetProcessNodes(){PROC_NODE_LIST mapResult;PROC_INFO_LIST infos = GetProcessInfos();for (const auto& item : infos){if (mapResult.end() != mapResult.find(item.first)){continue;}if (0 == item.second.dwParentPID ||infos.end() == infos.find(item.second.dwParentPID)){PROC_NODE node = _GetProcessNode(infos, item.first);mapResult.insert(std::make_pair(item.first, node));}}return mapResult;}MODULE_INFO_LIST GetModuleInfos(DWORD dwPID){MODULE_INFO_LIST 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.th32ProcessID = me32.th32ProcessID;info.GlblcntUsage = me32.GlblcntUsage;info.modBaseAddr = me32.modBaseAddr;info.modBaseSize = me32.modBaseSize;info.hModule = me32.hModule;info.strExePath = me32.szExePath;info.strModule = me32.szModule;vModules.push_back(info);} while (::Module32Next(hModuleSnap, &me32));} while (false);if (INVALID_HANDLE_VALUE != hModuleSnap){::CloseHandle(hModuleSnap);}return vModules;}PROC_NODE GetProcessNode(DWORD dwPID){PROC_INFO_LIST procInfos = GetProcessInfos();return _GetProcessNode(procInfos, dwPID);}PROC_NODE _GetProcessNode(const PROC_INFO_LIST& procInfos,DWORD dwPID){PROC_NODE procNode;for (auto& item : procInfos){const PROC_INFO& info = item.second;if (item.first == dwPID){procNode.ProcInfo = info;}else if (info.dwParentPID == dwPID){PROC_NODE subNode = _GetProcessNode(procInfos, info.dwPID);procNode.NodeList.push_back(subNode);}}return procNode;}bool KillProcess(const _tstring& strName/* = _T("")*/){bool fResult = true;PROC_INFO_LIST infos = GetProcessInfos(strName, 0);for (const auto& item : infos){if (!KillProcess(item.first)){fResult = false;}}return fResult;}bool 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 _KillProcessNode(const PROC_NODE& procNode){HANDLE hProcess = NULL;BOOL fSuccess = false;// 杀死子进程for (auto item : procNode.NodeList){_KillProcessNode(item);}// 杀死进程hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, procNode.ProcInfo.dwPID);if (NULL == hProcess){return false;}fSuccess = ::TerminateProcess(hProcess, 0);::CloseHandle(hProcess);return fSuccess;}bool KillProcessNode(DWORD dwPID){return _KillProcessNode(GetProcessNode(dwPID));}_tstring 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 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 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;}bool IsWow64Process(DWORD dwPID){HANDLE hProcess = NULL;bool fWow64 = false;do{hProcess = ::OpenProcess(GetQueryAccess(), FALSE, dwPID);if (NULL == hProcess){break;}BOOL Wow64Process = FALSE;if (!::IsWow64Process(hProcess, &Wow64Process)){break;}fWow64 = Wow64Process;} while (false);if (NULL != hProcess){::CloseHandle(hProcess);}return fWow64;}bool IsProcessX86(DWORD dwPID){return true == IsWow64Process(dwPID);}bool IsProcessX64(DWORD dwPID){return false == IsWow64Process(dwPID);}WORD 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 IsX86(DWORD dwPID){return IMAGE_FILE_MACHINE_I386 == GetMachine(dwPID);}bool IsX64(DWORD dwPID){return IMAGE_FILE_MACHINE_AMD64 == GetMachine(dwPID);}bool IsARM32(DWORD dwPID){WORD wMachine = GetMachine(dwPID);return wMachine >= IMAGE_FILE_MACHINE_ARM && wMachine <= IMAGE_FILE_MACHINE_ARMNT;}bool IsARM64(DWORD dwPID){return IMAGE_FILE_MACHINE_ARM64 == GetMachine(dwPID);}bool IsWindowsGUI(DWORD dwPID){return IMAGE_SUBSYSTEM_WINDOWS_GUI == GetSubsystemType(dwPID);}bool IsWindowsCUI(DWORD dwPID){return IMAGE_SUBSYSTEM_WINDOWS_CUI == GetSubsystemType(dwPID);}bool SuspendProcess(DWORD dwPID){typedef NTSTATUS(*_NtSuspendProcess)(HANDLE hProcess);_NtSuspendProcess NtSuspendProcess = NULL;HANDLE hProcess = NULL;HMODULE hModule = NULL;bool fResult = false;do{hModule = ::LoadLibrary(_T("ntdll.dll"));if (NULL == hModule){break;}hProcess = ::OpenProcess(PROCESS_SUSPEND_RESUME, FALSE, dwPID);if (NULL == hProcess){break;}NtSuspendProcess = (_NtSuspendProcess)::GetProcAddress(hModule, "NtSuspendProcess");if (NULL == NtSuspendProcess){break;}fResult = (STATUS_SUCCESS == NtSuspendProcess(hProcess));} while (false);if (hProcess){::CloseHandle(hProcess);}if (hModule){::FreeLibrary(hModule);}return fResult;}bool ResumeProcess(DWORD dwPID){typedef NTSTATUS(*_NtResumeProcess)(HANDLE hProcess);_NtResumeProcess NtResumeProcess = NULL;HANDLE hProcess = NULL;HMODULE hModule = NULL;bool fResult = false;do{hModule = ::LoadLibrary(_T("ntdll.dll"));if (NULL == hModule){break;}hProcess = ::OpenProcess(PROCESS_SUSPEND_RESUME, FALSE, dwPID);if (NULL == hProcess){break;}NtResumeProcess = (_NtResumeProcess)::GetProcAddress(hModule, "NtResumeProcess");if (NULL == NtResumeProcess){break;}fResult = (STATUS_SUCCESS == NtResumeProcess(hProcess));} while (false);if (hProcess){::CloseHandle(hProcess);}if (hModule){::FreeLibrary(hModule);}return fResult;}bool SuspendProcessNode(DWORD dwPID){return _SuspendProcessNode(GetProcessNode(dwPID));}bool ResumeProcessNode(DWORD dwPID){return _ResumeProcessNode(GetProcessNode(dwPID));}bool _SuspendProcessNode(const PROC_NODE& procNode){bool fResult = false;do{// 暂停主进程if (!SuspendProcess(procNode.ProcInfo.dwPID)){break;}// 暂停子进程for (const auto& item : procNode.NodeList){if (!_SuspendProcessNode(item)){break;}}fResult = true;} while (false);return fResult;}bool _ResumeProcessNode(const PROC_NODE& procNode){bool fResult = false;do{// 恢复主进程if (!ResumeProcess(procNode.ProcInfo.dwPID)){break;}// 恢复子进程for (const auto& item : procNode.NodeList){if (!_ResumeProcessNode(item)){break;}}fResult = true;} while (false);return fResult;}DWORD GetProcessHandleCount(DWORD dwPID){HANDLE hProcess = NULL;DWORD dwHandleCount = 0;DWORD dwGdiCount = 0;DWORD dwUserCount = 0;do{// 打开进程hProcess = ::OpenProcess(GetQueryAccess(), FALSE, dwPID);if (NULL == hProcess){break;}::GetProcessHandleCount(hProcess, &dwHandleCount);dwGdiCount = GetGuiResources(hProcess, GR_GDIOBJECTS);dwUserCount = GetGuiResources(hProcess, GR_USEROBJECTS);} while (false);if (NULL != hProcess){::CloseHandle(hProcess);}return dwHandleCount;}std::vector<PROCESS_GROUPS_INFO> GetProcessGroupsInfo(DWORD dwPID){std::vector<PROCESS_GROUPS_INFO> vResult;HANDLE hToken = NULL;PTOKEN_GROUPS pGroupInfo = NULL;SID_NAME_USE SidType = SidTypeUser;TCHAR szName[MAX_PATH] = { 0 };TCHAR szDomain[MAX_PATH] = { 0 };PSID pSID = NULL;SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;HANDLE hProcess = NULL;DWORD dwSize = 0;do{// 打开进程hProcess = ::OpenProcess(GetQueryAccess(), FALSE, dwPID);if (NULL == hProcess){break;}// 打开进程令牌if (!::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)){break;}// 获取令牌信息所需缓冲大小if (!::GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize)){if (ERROR_INSUFFICIENT_BUFFER != ::GetLastError()){break;}}// 分配缓冲pGroupInfo = (PTOKEN_GROUPS)::GlobalAlloc(GPTR, dwSize);if (NULL == pGroupInfo){break;}// 获取令牌组信息if (!::GetTokenInformation(hToken, TokenGroups, pGroupInfo, dwSize, &dwSize)){break;}// 分配和初始化一个安全标识符if (!::AllocateAndInitializeSid(&SIDAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,0, 0, 0, 0, 0, 0,&pSID)){break;}// 检索SID信息for (DWORD i = 0; i < pGroupInfo->GroupCount; i++){PROCESS_GROUPS_INFO info;dwSize = _countof(szName);if (!::LookupAccountSid(NULL, pGroupInfo->Groups[i].Sid, szName, &dwSize, szDomain, &dwSize, &SidType)){if (ERROR_NONE_MAPPED != ::GetLastError()){break;}_tcscpy_s(szName, dwSize, _T("NONE_MAPPED"));}LPTSTR pStringSid = NULL;if (ConvertSidToStringSid(pGroupInfo->Groups[i].Sid, &pStringSid)){info.SID = pStringSid;::LocalFree(pStringSid);}info.DomainName = szDomain;info.UserName = szName;info.Attributes = pGroupInfo->Groups[i].Attributes;vResult.push_back(info);}} while (false);if (pSID){::FreeSid(pSID);}if (pGroupInfo){::GlobalFree(pGroupInfo);}if (NULL != hProcess){::CloseHandle(hProcess);}return vResult;}DWORD _DuplicateProcessToken(const _tstring& strName,DWORD dwSessionId,DWORD dwDesiredAccess,PHANDLE phToken){PROCESSENTRY32 pe = { 0 };PRIVILEGE_SET ps = { 0 };HANDLE hSnapshot = INVALID_HANDLE_VALUE;BOOL fResult = FALSE;DWORD dwErr = ERROR_SUCCESS;BOOL fFound = FALSE;ps.PrivilegeCount = 1;ps.Control = PRIVILEGE_SET_ALL_NECESSARY;do{if (!::LookupPrivilegeValue(NULL, SE_TCB_NAME, &ps.Privilege[0].Luid)){break;}hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (INVALID_HANDLE_VALUE == hSnapshot){break;}pe.dwSize = sizeof(pe);if (!::Process32First(hSnapshot, &pe)){break;}do{HANDLE hProcess = NULL;HANDLE hToken = NULL;DWORD dwRetLen = 0;DWORD sid = 0;if (0 != _tcsicmp(pe.szExeFile, strName.c_str())){continue;}hProcess = ::OpenProcess(GetQueryAccess(), FALSE, pe.th32ProcessID);if (!hProcess){break;}do{BOOL fTcb = FALSE;if (!::OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_DUPLICATE, &hToken)){break;}if (!::PrivilegeCheck(hToken, &ps, &fTcb) && fTcb){break;}if (!::GetTokenInformation(hToken, TokenSessionId, &sid, sizeof(sid), &dwRetLen) && sid == dwSessionId){break;}if (!::DuplicateTokenEx(hToken, dwDesiredAccess, NULL, SecurityImpersonation, TokenImpersonation, phToken)){break;}fFound = true;dwErr = ERROR_SUCCESS;} while (false);if (hToken){::CloseHandle(hToken);}if (hProcess){::CloseHandle(hProcess);}if (fFound){break;}} while (::Process32Next(hSnapshot, &pe));if (!fFound){dwErr = ERROR_NOT_FOUND;break;}fResult = true;} while (false);if (!fResult){dwErr = ::GetLastError();if (!fFound){dwErr = ERROR_NOT_FOUND;}}if (INVALID_HANDLE_VALUE != hSnapshot){::CloseHandle(hSnapshot);}return dwErr;}DWORD _CreateProcessWithUIAccess(const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir/* = _T("")*/,bool fUIAccess/* = true*/){HANDLE hTokenUIAccess = NULL;DWORD dwErr = ERROR_SUCCESS;BOOL fResult = FALSE;_tstring exePath = strExePath;_tstring exeCommand = strCommand;_tstring exeCurDir = strCurDir;LPCTSTR lpApplicationName = NULL;LPTSTR lpCommandLine = NULL;LPCTSTR lpCurrentDir = NULL;if (!strExePath.empty()){lpApplicationName = exePath.c_str();}if (!strCommand.empty()){lpCommandLine = (LPTSTR)exeCommand.c_str();}if (!exeCurDir.empty()){lpCurrentDir = exeCurDir.c_str();}do{STARTUPINFO si = { 0 };PROCESS_INFORMATION pi = { 0 };dwErr = _CreateUIAccessToken(&hTokenUIAccess);if (ERROR_SUCCESS != dwErr){break;}if (!fUIAccess){BOOL fTokenInformation = FALSE;::SetTokenInformation(hTokenUIAccess, TokenUIAccess, &fTokenInformation, sizeof(fTokenInformation));}::GetStartupInfo(&si);if (!::CreateProcessAsUser(hTokenUIAccess, lpApplicationName, lpCommandLine, NULL, NULL, FALSE, 0, NULL, lpCurrentDir, &si, &pi)){break;}::CloseHandle(pi.hProcess);::CloseHandle(pi.hThread);} while (false);if (!fResult){dwErr = ::GetLastError();}if (hTokenUIAccess){::CloseHandle(hTokenUIAccess);}return dwErr;}bool CreateProcessWithPidToken(DWORD pid,const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir){STARTUPINFOW si = { 0 };PROCESS_INFORMATION pi = { 0 };HANDLE hProcess = NULL;HANDLE hProcessToken = NULL;HANDLE hDuplicateToken = NULL;bool fResult = false;si.cb = sizeof(STARTUPINFO);std::wstring exePath = _TStrToWStr(strExePath);std::wstring exeCommand = _TStrToWStr(strCommand);std::wstring exeCurDir = _TStrToWStr(strCurDir);LPCWSTR lpApplicationName = NULL;LPWSTR lpCommandLine = NULL;LPCWSTR lpCurrentDir = NULL;if (!exePath.empty()){lpApplicationName = exePath.c_str();}if (!exeCommand.empty()){lpCommandLine = (LPWSTR)exeCommand.c_str();}if (!exeCurDir.empty()){lpCurrentDir = exeCurDir.c_str();}do{// 打开进程句柄hProcess = ::OpenProcess(GetQueryAccess(), TRUE, pid);if (NULL == hProcess){break;}// 打开进程令牌DWORD dwOpenDesiredAccess = TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY;if (!::OpenProcessToken(hProcess, dwOpenDesiredAccess, &hProcessToken)){break;}// 模拟登录用户if (!::ImpersonateLoggedOnUser(hProcessToken)){break;}// 终止客户端应用程序的模拟::RevertToSelf();// 创建一个复制现有令牌的新访问令牌DWORD dwDuplicateDesiredAccess = TOKEN_ADJUST_DEFAULT | TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY;if (!::DuplicateTokenEx(hProcessToken, dwDuplicateDesiredAccess, NULL, SecurityImpersonation, TokenPrimary, &hDuplicateToken)){break;}// 使用令牌创建进程// 调用 CreateProcessWithTokenW 的进程必须具有SE_IMPERSONATE_NAME特权。if (!::CreateProcessWithTokenW(hDuplicateToken, LOGON_WITH_PROFILE, lpApplicationName, lpCommandLine, 0, NULL, lpCurrentDir, &si, &pi)){break;}fResult = true;::CloseHandle(pi.hProcess);::CloseHandle(pi.hThread);} while (false);if (hDuplicateToken){::CloseHandle(hDuplicateToken);}if (hProcessToken){::CloseHandle(hProcessToken);}if (hProcess){::CloseHandle(hProcess);}return fResult;}DWORD _CreateUIAccessToken(PHANDLE phToken){DWORD dwErr = ERROR_SUCCESS;HANDLE hTokenSelf = NULL;HANDLE hWinlogonToken = NULL;BOOL fResult = FALSE;do{DWORD dwDesiredAccess = TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_DEFAULT;DWORD dwSessionId = 0;DWORD dwRetLen = 0;BOOL bUIAccess = TRUE;if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hTokenSelf)){break;}if (!::GetTokenInformation(hTokenSelf, TokenSessionId, &dwSessionId, sizeof(dwSessionId), &dwRetLen)){break;}dwErr = _DuplicateProcessToken(_T("winlogon.exe"), dwSessionId, TOKEN_IMPERSONATE, &hWinlogonToken);if (ERROR_SUCCESS != dwErr){break;}if (!::SetThreadToken(NULL, hWinlogonToken)){break;}if (!::DuplicateTokenEx(hTokenSelf, dwDesiredAccess, NULL, SecurityAnonymous, TokenPrimary, phToken)){break;}if (!::SetTokenInformation(*phToken, TokenUIAccess, &bUIAccess, sizeof(bUIAccess))){break;}::RevertToSelf();fResult = TRUE;} while (false);if (!fResult){if (*phToken){::CloseHandle(*phToken);*phToken = NULL;}dwErr = ::GetLastError();}if (hWinlogonToken){::CloseHandle(hWinlogonToken);}if (hTokenSelf){::CloseHandle(hTokenSelf);}return dwErr;}DWORD CreateProcessWithUIAccess(const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir/* = _T("")*/){return _CreateProcessWithUIAccess(strExePath, strCommand, strCurDir, true);}DWORD CreateProcessNoUIAccess(const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir/* = _T("")*/){return _CreateProcessWithUIAccess(strExePath, strCommand, strCurDir, false);}bool CreateProcessWithSystem(const _tstring& strExePath,const _tstring& strCommand,const _tstring& strCurDir/* = _T("")*/){PROC_INFO_LIST infos = GetProcessInfos(_T("winlogon.exe"), 0);if (infos.empty()){return false;}return CreateProcessWithPidToken(infos.begin()->first, strExePath, strCommand, strCurDir);}BOOL CheckProcessUIAccess(DWORD dwPid,DWORD* pdwErr,DWORD* pfUIAccess){HANDLE hProcess = NULL;HANDLE hToken = NULL;DWORD dwRetLen = 0;BOOL result = FALSE;do{hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);if (!hProcess){break;}if (!::OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)){break;}if (!::GetTokenInformation(hToken, TokenUIAccess, pfUIAccess, sizeof(*pfUIAccess), &dwRetLen)){break;}result = TRUE;} while (false);if (!result){*pdwErr = ::GetLastError();}if (hProcess){::CloseHandle(hProcess);}if (hToken){::CloseHandle(hToken);}return result;}void _EnumProcessWindows(std::map<HWND, WND_INFO>& infos, HWND hWnd, DWORD dwPid){HWND childWindow = NULL;ULONG nMaxTimes = 0x4000;//使用 FindWindowEx 函数搜索子窗口while (nMaxTimes > 0 && (childWindow = ::FindWindowEx(hWnd, childWindow, NULL, NULL))){ULONG processId = 0;ULONG threadId = 0;threadId = ::GetWindowThreadProcessId(childWindow, &processId);if (dwPid == processId){TCHAR szClassBuf[MAX_PATH] = { 0 };TCHAR szTextBuf[MAX_PATH] = { 0 };::GetClassName(childWindow, szClassBuf, _countof(szClassBuf));::GetWindowText(childWindow, szTextBuf, _countof(szTextBuf));WND_INFO info;info.hWnd = childWindow;info.dwPid = processId;info.dwTid = threadId;info.strClass = szClassBuf;info.strText = szTextBuf;infos.insert(std::make_pair(childWindow, info));}nMaxTimes--;}}std::map<HWND, WND_INFO> GetProcessWindows(DWORD dwPid){std::map<HWND, WND_INFO> infos;//枚举 桌面窗口 的子窗口_EnumProcessWindows(infos, ::GetDesktopWindow(), dwPid);//枚举 仅消息窗口 的子窗口_EnumProcessWindows(infos, HWND_MESSAGE, dwPid);return infos;}WND_NODE _GetWindowNode(HWND hWnd, std::vector<MODULE_INFO>& modules){TCHAR szClassBuf[MAX_PATH] = { 0 };TCHAR szTextBuf[MAX_PATH] = { 0 };::GetClassName(hWnd, szClassBuf, _countof(szClassBuf));::GetWindowText(hWnd, szTextBuf, _countof(szTextBuf));WND_NODE node;node.hWnd = hWnd;node.strClass = szClassBuf;node.strText = szTextBuf;node.dwTid = ::GetWindowThreadProcessId(hWnd, &node.dwPid);HMODULE hModule = (HMODULE)::GetWindowLongPtr(hWnd, GWLP_HINSTANCE);for (const auto& item : modules){if (hModule == item.hModule){node.strModule = item.strModule;}}HWND childWindow = NULL;ULONG nMaxTimes = 0x4000;//使用 FindWindowEx 函数搜索子窗口while (nMaxTimes > 0 && (childWindow = ::FindWindowEx(hWnd, childWindow, NULL, NULL))){node.NodeList.push_back(_GetWindowNode(childWindow, modules));nMaxTimes--;}return node;}std::map<HWND, WND_NODE> GetProcessWindowNodes(DWORD dwPid){std::map<HWND, WND_NODE> nodes;std::map<HWND, WND_INFO> infos;std::vector<MODULE_INFO> moduleInfos = GetModuleInfos(dwPid);//枚举 桌面窗口 的子窗口_EnumProcessWindows(infos, ::GetDesktopWindow(), dwPid);//枚举 仅消息窗口 的子窗口_EnumProcessWindows(infos, HWND_MESSAGE, dwPid);for (const auto& item : infos){WND_NODE node = _GetWindowNode(item.first, moduleInfos);nodes.insert(std::make_pair(item.first, node));}return nodes;}#pragma pack(push)
#pragma pack(1)// 包含文件的版本信息。 此信息与语言和代码页无关// https://learn.microsoft.com/zh-cn/windows/win32/menurc/vs-versioninfotypedef struct {WORD             wLength;       // VS_VERSIONINFO 结构的长度(以字节为单位),此长度不包括在 32 位边界上对齐任何后续版本资源数据的填充WORD             wValueLength;  // Value 成员的长度(以字节为单位)WORD             wType;         // 版本资源中的数据类型, 1: 资源包含文本数据 0: 版本资源包含二进制数据WCHAR            szKey[15];     // Unicode 字符串 L“VS_VERSION_INFO”WORD             Padding1;      // 在 32 位边界上对齐 Children 成员所需的任意或零个 WORD//VS_FIXEDFILEINFO Value//WORD             Padding2//WORD             Children} VS_VERSIONINFO, * PVS_VERSIONINFO;#pragma pack(pop)static VERSION_LIST _GetFileVersionList(const _tstring& strFile, bool fLocalised){VERSION_LIST infoResult;PVOID pFsRedirectionOldValue = NULL;bool isDisableWow64Fs = false;UINT cbTranslate = 0;DWORD dwVerSize;LPVOID lpVerData = NULL;// 加载文件if (strFile.empty()){return infoResult;}// 禁用文件重定向isDisableWow64Fs = ::Wow64DisableWow64FsRedirection(&pFsRedirectionOldValue);do{DWORD dwFlags = fLocalised ? FILE_VER_GET_LOCALISED : FILE_VER_GET_NEUTRAL;dwFlags |= FILE_VER_GET_PREFETCHED;// 获取版本信息数据大小dwVerSize = ::GetFileVersionInfoSize(strFile.c_str(), NULL);//dwVerSize = ::GetFileVersionInfoSizeEx(dwFlags, strFile.c_str(), NULL);if (0 == dwVerSize){break;}// 分配版本信息缓冲lpVerData = ::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwVerSize);if (!lpVerData){break;}// 获取版本信息BOOL fResult = FALSE;fResult = ::GetFileVersionInfo(strFile.c_str(), NULL, dwVerSize, lpVerData);//fResult = ::GetFileVersionInfoEx(dwFlags, strFile.c_str(), NULL, dwVerSize, lpVerData);if (!fResult){break;}// 获取语言代码LANGANDCODEPAGE* lpTranslate = NULL;if (!::VerQueryValue(lpVerData, _T("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate)){break;}DWORD dwCount = cbTranslate / sizeof(LANGANDCODEPAGE);for (DWORD i = 0; i < dwCount; i++){LANGANDCODEPAGE langCodePage = lpTranslate[i];VERSION_INFO versionInfo;// 获取 VS_FIXEDFILEINFO 信息PVS_VERSIONINFO lpVersion = (PVS_VERSIONINFO)lpVerData;if (0 != lpVersion->wValueLength){VS_FIXEDFILEINFO* pFixedFileInfo = (VS_FIXEDFILEINFO*)((LPBYTE)lpVersion + sizeof(VS_VERSIONINFO));DWORD dwAlign = 4;DWORD_PTR dwPadding = ((DWORD_PTR)pFixedFileInfo % dwAlign);if (0 != dwPadding){pFixedFileInfo = (VS_FIXEDFILEINFO*)((LPBYTE)pFixedFileInfo + (dwAlign - dwPadding));}versionInfo.vsFixedInfo = *((PVS_VER_FIXEDFILEINFO)pFixedFileInfo);}// 查询所有信息// 查询单个信息函数auto _QueryInfo = [](const _tstring& strName, const LPVOID lpData, const LANGANDCODEPAGE& code) {TCHAR strQuery[MAX_PATH] = { 0 };LPCTSTR lpQueryRes = NULL;UINT uQueryCchSize;(void)::StringCchPrintf(strQuery, _countof(strQuery),_T("\\StringFileInfo\\%04x%04x\\%s"),code.wLanguage, code.wCodePage, strName.c_str());if (::VerQueryValue(lpData, strQuery, (LPVOID*)&lpQueryRes, &uQueryCchSize)){return lpQueryRes;}return _T("");};auto _GetVersionStr = [](VERSON_NUMBER hi, VERSON_NUMBER lo) -> _tstring {TCHAR szBuf[MAX_PATH] = { 0 };(void)::StringCchPrintf(szBuf, _countof(szBuf), _T("%hd.%hd.%hd.%hd"),hi.Version.wHigh,hi.Version.wLow,lo.Version.wHigh,lo.Version.wLow);return szBuf;};auto _GetLanguageNameStr = [](LANGANDCODEPAGE langCodePage) -> _tstring {TCHAR szBuf[MAX_PATH] = { 0 };::VerLanguageName(langCodePage.wLanguage, szBuf, _countof(szBuf));return szBuf;};versionInfo.langAndCodePage = langCodePage;versionInfo.strComments = _QueryInfo(_T("Comments"), lpVerData, langCodePage);versionInfo.strInternalName = _QueryInfo(_T("InternalName"), lpVerData, langCodePage);versionInfo.strProductName = _QueryInfo(_T("ProductName"), lpVerData, langCodePage);versionInfo.strCompanyName = _QueryInfo(_T("CompanyName"), lpVerData, langCodePage);versionInfo.strLegalCopyright = _QueryInfo(_T("LegalCopyright"), lpVerData, langCodePage);versionInfo.strProductVersion = _QueryInfo(_T("ProductVersion"), lpVerData, langCodePage);versionInfo.strFileDescription = _QueryInfo(_T("FileDescription"), lpVerData, langCodePage);versionInfo.strLegalTrademarks = _QueryInfo(_T("LegalTrademarks"), lpVerData, langCodePage);versionInfo.strPrivateBuild = _QueryInfo(_T("PrivateBuild"), lpVerData, langCodePage);versionInfo.strFileVersion = _QueryInfo(_T("FileVersion"), lpVerData, langCodePage);versionInfo.strOriginalFilename = _QueryInfo(_T("OriginalFilename"), lpVerData, langCodePage);versionInfo.strSpecialBuild = _QueryInfo(_T("SpecialBuild"), lpVerData, langCodePage);VS_VER_FIXEDFILEINFO& vsFixedInfo = versionInfo.vsFixedInfo;versionInfo.strFileVersionEx = _GetVersionStr(vsFixedInfo.dwFileVersionMS, vsFixedInfo.dwFileVersionLS);versionInfo.strProductVersionEx = _GetVersionStr(vsFixedInfo.dwProductVersionMS, vsFixedInfo.dwProductVersionLS);versionInfo.strLanguageName = _GetLanguageNameStr(langCodePage);versionInfo.FileVerNumber = versionInfo.strFileVersionEx.c_str();versionInfo.ProductVerNumber = versionInfo.strProductVersionEx.c_str();infoResult.emplace(langCodePage, versionInfo);}} while (false);// 恢复文件重定向if (isDisableWow64Fs){::Wow64RevertWow64FsRedirection(pFsRedirectionOldValue);}if (lpVerData){::HeapFree(::GetProcessHeap(), 0, lpVerData);lpVerData = NULL;}return infoResult;}VERSION_LIST GetFileVersionList(const _tstring& strFile, bool fLocalised/* = true*/){VERSION_LIST fileInfos = _GetFileVersionList(strFile, fLocalised);return fileInfos;}VERSION_INFO GetFileVersion(const _tstring& strFile, bool fLocalised/* = true*/){VERSION_INFO info;VERSION_LIST fileInfos = _GetFileVersionList(strFile, fLocalised);if (!fileInfos.empty()){info = fileInfos.begin()->second;}return info;}
}

main.cpp

#include <locale.h>
#include <tchar.h>
#include "Win32Utils/CProcessUtils.h"int _tmain(int argc, LPCTSTR argv[])
{setlocale(LC_ALL, "");CProcessUtils::PROC_INFO_LIST procList = CProcessUtils::GetProcessInfos();return 0;
}

关键字:南宁网站建设设计制作_宁波专业优化网站制作公司_企业营销策划方案范文_关键词seo排名

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: