首页 > 系统相关 >获取windows内存、cpu及进程的信息

获取windows内存、cpu及进程的信息

时间:2022-11-30 16:45:58浏览次数:41  
标签:status return windows PRIVILEGES 内存 printf 进程 NULL cpu

如题,想获取进程信息用于资源显示,在这个过程中遇到很多问题,看来需要了解下windows里面的东西才行。记录目前遇到的问题,不断更新直到解决。

头文件需要

#include <TlHelp32.h>
#include <Psapi.h>
#include <Pdh.h>
#pragma comment(lib,"pdh.lib")
#pragma comment(lib, "Psapi.lib")

定义一些全局变量

typedef unsigned long long TimeT;

unsigned long m_nInterval;
void* m_hQuery;
void* m_hcCpuTime;
void* m_hcMemTime;
double m_dbTotalMem;

void* m_hSnapshot;
std::vector<std::string> m_vecPaths;

bool InitPDH()
{
    PDH_STATUS status = PdhOpenQueryA(NULL, NULL, &m_hQuery); // 创建用于管理性能数据收集的新查询
    if (status != ERROR_SUCCESS)
    {
        printf("PdhOpenQuery failed with status 0x%x.\n", status);
        return false;
    }
    // PdhAddCounterA 将指定的计数器添加到查询
    status = PdhAddCounterA(m_hQuery, "\\Processor(_Total)\\% Processor Time", NULL, &m_hcCpuTime); // cpu使用率命令,所有CPU占用率,这个值在多核系统中会超过100%。包含空闲线程的CPU占用率
    if (status != ERROR_SUCCESS)
    {
        printf("PdhAddCounter Processor Time failed with status 0x%x.\n", status); 
        return false;
    }
    status = PdhAddCounterA(m_hQuery, "\\Memory\\Available MBytes", NULL, &m_hcMemTime);// 剩余的可用物理内存,单位兆字节,MB,
    if (status != ERROR_SUCCESS)
    {
        printf("PdhAddCounter Disk Time failed with status 0x%x.\n", status);
        return false;
    }

    MEMORYSTATUSEX st = { 0 };
    st.dwLength = sizeof(MEMORYSTATUSEX);
    GlobalMemoryStatusEx(&st);
    m_dbTotalMem = st.ullTotalPhys / (1024.0*1024.0);  // 物理内存 MB

    // CreateToolhelp32Snapshot
    // 可以通过获取进程信息为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程建立一个快照。
    // 用来指定“快照”中需要返回的对象,可以是TH32CS_SNAPPROCESS(在快照中包含系统中所有的进程)等
    // 一个进程ID号,用来指定要获取哪一个进程的快照,当获取系统进程列表或获取当前进程快照时可以设为0
    m_hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (INVALID_HANDLE_VALUE == m_hSnapshot)
    {
        printf("CreateToolhelp32Snapshot failed with status 0x%x.\n", GetLastError());
        return false;
    }

    return CollectData();
}

获取cpu、内存查询

TimeT getCurrentTime()
{
    time_t now_time = time(NULL);
    tm* t_tm = localtime(&now_time);
    printf("local time is : %s\n", asctime(t_tm));
    return now_time;
}

float getMemTime()
{
    PDH_FMT_COUNTERVALUE counterVal;
    PDH_STATUS status = PdhGetFormattedCounterValue(m_hcMemTime, PDH_FMT_DOUBLE, NULL, &counterVal);
    if (status == ERROR_SUCCESS)
    {
        printf("memory time is: %f\n",100.0 * (m_dbTotalMem - counterVal.doubleValue) / m_dbTotalMem);
        return 100.0 * (m_dbTotalMem - counterVal.doubleValue) / m_dbTotalMem;
    }
    return 0;
}
float getCpuTime()
{
    PDH_FMT_COUNTERVALUE counterVal;
    PDH_STATUS status = PdhGetFormattedCounterValue(m_hcCpuTime, PDH_FMT_DOUBLE, NULL, &counterVal);
    if (status == ERROR_SUCCESS)
    {
        printf("cpu time is: %f\n",counterVal.doubleValue);
        return counterVal.doubleValue;
    }
    return 0;
}

查当前系统内的进程,这里遇到了问题

OpenProcess 无法通过
bool CollectData()
{
    PDH_STATUS status = PdhCollectQueryData(m_hQuery);// 收集指定查詢中所有計數器的目前原始資料值,並更新每個計數器的狀態碼。
    if (status != ERROR_SUCCESS)
    {
        printf("PdhCollectQueryData failed with status 0x%x.\n", status);
        return false;
    }
    char path[MAX_PATH];
    PROCESSENTRY32 pi = { 0 }; // 描述擷取快照集時,位於系統位址空間中的進程清單中的專案。用来存放快照进程信息的一个结构体。
    pi.dwSize = sizeof(PROCESSENTRY32); // The size of the structure, in bytes. 
    BOOL bRet = Process32First(m_hSnapshot, &pi);// Captures information about the first process encountered in the system snapshot set.指向第一个进程信息
    while (bRet)
    {
        // OpenProcess来获得进程的句柄
        // PROCESS_ALL_ACCESS 所有能获得的权限 ,表示所得到的进程句柄是否可以被继承, 被打开进程的PID
        // HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pi.th32ProcessID);//GetLastError 87 参数错误
        // 不成功可能是没有权限SeDebugPrivilege
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 5476); // GetLastError 5 拒绝访问
        int err = GetLastError();
        if (hProcess)
        {
            GetModuleFileNameEx(hProcess, NULL, path, MAX_PATH);
           // ......
            CloseHandle(hProcess);
        }
        bRet = Process32Next(m_hSnapshot, &pi);
    }
    return true;
}

        这里有个类型转换问题,char* 、 wchar_t* 和 string 转

        把属性页里字符集原来的使用Unicode字符集去掉或换成其他的(比如使用多字节字符集,没试过)就可以如上不转类型了。

        

 

 看网上应该要提升进程权限,添加如下代码

int   AddPrivilege(const   char   *Name) 
{
    HANDLE hPro = GetCurrentProcess();
    int d = GetLastError();
    /*
    要修改一个进程的访问令牌,首先要获得进程访问令牌的句柄,这可以通过OpenProcessToken得到
    BOOL OpenProcessToken(
    HANDLE ProcessHandle,   //要修改访问权限的进程句柄;
    DWORD DesiredAccess,   //指定你所需要的操作类型;
    PHANDLE TokenHandle     //返回的访问令牌指针
    );
    如要修改令牌我们要指定第二个参数为TOKEN_ADJUST_PRIVILEGES(其它一些参数可参考Platform SDK)。
    通过这个函数我们就可以得到当前进程的访问令牌的句柄(指定函数的第一个参数为GetCurrentProcess()就可以了)
    */
    HANDLE   hToken; 
    if   (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken)) 
    { 
#ifdef   _DEBUG 
        printf( "OpenProcessToken   error.\n "); 
#endif 
        return   1; 
    }
    int b = GetLastError();
    /*
    我们要怎么样才能知道一个权限对应的LUID值是多少呢?这就要用到另外一个API函数LookupPrivilegevalue,其原形如下:
BOOL     LookupPrivilegevalue(
            LPCTSTR     lpSystemName,       // system name,第一个参数是系统的名称,如果是本地系统只要指明为NULL就可以了
            LPCTSTR     lpName,             // privilege name,第二个参数就是指明了权限的名称,如“SeDebugPrivilege”
            PLUID     lpLuid                // locally unique identifier,第三个参数就是返回LUID的指针
);    */
    LUID   Luid;
    if   (!LookupPrivilegeValue(NULL,Name,&Luid)) 
    { 
#ifdef   _DEBUG 
        printf( "LookupPrivilegeValue   error.\n "); 
#endif 
        return   1; 
    }
    int c = GetLastError();
    TOKEN_PRIVILEGES   tp; 
    tp.PrivilegeCount   =   1; 
    tp.Privileges[0].Attributes   =   SE_PRIVILEGE_ENABLED; 
    tp.Privileges[0].Luid   =   Luid;
    /* 
    可以调用AdjustTokenPrivileges对这个访问令牌进行修改。
    BOOL  AdjustTokenPrivileges(
          HANDLE    TokenHandle,                    // handle to token ,第一个参数是访问令牌的句柄;
          BOOL    DisableAllPrivileges,             // disabling option,第二个参数决定是进行权限修改还是除能(Disable)所有权限;
        // 第三个参数指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组,数据组的每个项指明了权限的类型和要进行的操作; 
          PTOKEN_PRIVILEGES    NewState,            // privilege information
        // 第四个参数是结构PreviousState的长度,如果PreviousState为空,该参数应为NULL;
          DWORD    BufferLength,                    // size of buffer
        // 第五个参数也是一个指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息,可空;
          PTOKEN_PRIVILEGES    PreviousState,       // original state buffer
          PDWORD    ReturnLength                    // required buffer size,最后一个参数为实际PreviousState结构返回的大小。
    );
    typedef struct _TOKEN_PRIVILEGES     {   
            DWORD     PrivilegeCount;               // 数组原素的个数
            LUID_AND_ATTRIBUTES     Privileges[];   
    }     TOKEN_PRIVILEGES,  *PTOKEN_PRIVILEGES;       
    typedef struct _LUID_AND_ATTRIBUTES     {   
        // 第一个参数就是指权限的类型,是一个LUID的值,LUID就是指locally unique identifier,LUID是一个64位的值
            LUID         Luid;   
        // 第二个参数就指明了我们要进行的操作类型,有三个可选项:SE_PRIVILEGE_ENABLED、SE_PRIVILEGE_ENABLED_BY_DEFAULT、SE_PRIVILEGE_USED_FOR_ACCESS。
            DWORD       Attributes;   
    }     LUID_AND_ATTRIBUTES,     *PLUID_AND_ATTRIBUTES    */
    DWORD dw=0;
    //if   (!AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) 
        if   (!AdjustTokenPrivileges(hToken, FALSE, &tp,0, (PTOKEN_PRIVILEGES)NULL, &dw)) 
    { 
#ifdef   _DEBUG 
        printf( "AdjustTokenPrivileges   error.\n "); 
#endif 
        return   1; 
    }
        //ERROR_NOT_ALL_ASSIGNED
    int a = GetLastError();//1300 并非所有被引用的特权都指派给呼叫方
    CloseHandle(hToken);
    return   0; 
} 

结果

AdjustTokenPrivileges 没有成功

标签:status,return,windows,PRIVILEGES,内存,printf,进程,NULL,cpu
From: https://www.cnblogs.com/lely/p/16938933.html

相关文章

  • C语言动态内存管理
    在学习和使用C语言的过程中经常要编写管理内存的程序,往往提心吊胆。若是不想踩雷,唯一的办法就是深入理解内存管理,发现所有的陷阱并排除他们。内存的使用方式内存主要有三种......
  • 小内存场合LVGL截图为BMP格式保存至基于FATFS文件系统的SD卡
    1.引言截图是很多应用场合都需要的一项功能,对于无外存等小内存场合,同时又无法读取像素点的情况,截图通常需要多个组件的配合。本文采用的STM32G4微控制器,使用的组件如下:......
  • windows 7 安装 office2010错误1316.指定的账户已存在
    本机原有office2007通过控制面板卸载不成功1.通过软件“Office2007卸载工具_1.0.0.0.msi”先把2007卸载掉2.打开“MPInstallAndUninstall2.1.6”选种office2007点击......
  • 盘点macOS和Windows 的那些不同之处
    很多用了很多年Windows系统的朋友来说,下定决心觉得入手Mac,结果一上手发现怎么跟Windows完全不一样?其实细看就会发现,其中一个逻辑就是“反过来的”~比如说: “开始”按钮Win......
  • vscode扩展太多占内存如何改路径?(windows)
    比较完美的解决方法如下1.进入官网https://code.visualstudio.com/选择下载zip版本的visualstudiocode2.下载好过后自行解压到目录,然后到vistualstudiocode的......
  • windows 利用IIS环境配置FTP目录以及用户隔离
    1、安装IIS(轻车熟路暂不赘述)2、如果需要满足不同用户根据不同账号登录FTP首先在Windows的用户管理中建立不同的用户3、IIS上建立FTP站点,   设置为: 授权规则......
  • windows下编译调试 Elasticsearch 8.7.0 源码
    最近想从代码层面学习下ElasticSearch,于是下载代码并导入到idea中,开始一顿操作,gradle各种倒腾,还是没法直接从代码运行进程,最后选择了一种不那么直接的debug方法,远程......
  • OpenStack跨CPU热迁移失败处理
    1.注释libvirt的CPU检测代码所有计算节点vim/usr/lib/python3/dist-packages/nova/virt/libvirt/driver.py'''9342#try:9343#ifnotins......
  • 监听Windows(生成木马)
    sudosu msfvenom-ax86--platformwindows-pwindows/meterpreter/reverse_tcpLHOST=ip地址LPORT=端口-fexe-otest.exe注意:把生成的文件拷贝到windows虚拟机......
  • 【文章精选集锦】Java 内存模型与 volatile :happens-before,重排序,内存屏障
    【文章精选集锦】Java内存模型与volatile:happens-before,重排序,内存屏障Kotlin开发者社区 3天前很多时候,千言万语不如一张图:  停停停,发错了,看下面的JVM内存模型图: ......