WIN10 API打印CPU占用率

环境:win10+VS2017

网上找了几个demo发现CPU占用率不准确,跟任务管理器不一样。最后参考github项目GitHub - zhongyang219/TrafficMonitor: 这是一个用于显示当前网速、CPU及内存利用率的桌面悬浮窗软件,并支持任务栏显示,支持更换皮肤。,能过获取比较准确的CPU占用率。

注意要一秒获取一次CPU占用率,时间太短就不准确了。

WinVersionHelper.h

#pragma once

#define g_winVerHelper CWinVersionHelper::instance()

class CWinVersionHelper
{
public:
    static CWinVersionHelper& instance();

	CWinVersionHelper();
	~CWinVersionHelper();

	bool IsWindows10FallCreatorOrLater() const;		// 判断当前Windows版本是否为Win10秋季创意者更新或更新的版本
	bool IsWindows7() const;					    // 判断Windows版本是否为Windows7
	bool IsWindows8Or8point1() const;			    // 判断Windows版本是否为Windows8或Windows8.1
    bool IsWindows8OrLater() const;
    bool IsWindows10OrLater() const;

	int GetMajorVersion() const { return m_major_version; }
	int GetMinorVersion() const { return m_minor_version; }
	int GetBuildNumber() const { return m_build_number; }
protected:
	int m_major_version{};
	int m_minor_version{};
	int m_build_number{};
};

WinVersionHelper.cpp

#include "WinVersionHelper.h"
#include <Windows.h>


CWinVersionHelper& CWinVersionHelper::instance()
{
    static CWinVersionHelper s_instance;
    return s_instance;
}

CWinVersionHelper::CWinVersionHelper()
{
	DWORD dwMajorVer{}, dwMinorVer{}, dwBuildNumber{};
	HMODULE hModNtdll{};
	if (hModNtdll = ::LoadLibraryW(L"ntdll.dll"))
	{
		typedef void (WINAPI *pfRTLGETNTVERSIONNUMBERS)(DWORD*, DWORD*, DWORD*);
		pfRTLGETNTVERSIONNUMBERS pfRtlGetNtVersionNumbers;
		pfRtlGetNtVersionNumbers = (pfRTLGETNTVERSIONNUMBERS)::GetProcAddress(hModNtdll, "RtlGetNtVersionNumbers");
		if (pfRtlGetNtVersionNumbers)
		{
			pfRtlGetNtVersionNumbers(&dwMajorVer, &dwMinorVer, &dwBuildNumber);
			dwBuildNumber &= 0x0ffff;
		}
		::FreeLibrary(hModNtdll);
		hModNtdll = NULL;
	}
	m_major_version = dwMajorVer;
	m_minor_version = dwMinorVer;
	m_build_number = dwBuildNumber;
}


CWinVersionHelper::~CWinVersionHelper()
{
}

bool CWinVersionHelper::IsWindows10FallCreatorOrLater() const
{
	if (m_major_version > 10)
		return true;
	else if (m_major_version == 10 && m_minor_version > 0)
		return true;
	else if (m_major_version == 10 && m_minor_version == 0 && m_build_number >= 16299)
		return true;
	else return false;
}

bool CWinVersionHelper::IsWindows7() const
{
	return (m_major_version == 6 && m_minor_version == 1);
}

bool CWinVersionHelper::IsWindows8Or8point1() const
{
	return (m_major_version == 6 && m_minor_version > 1);
}

bool CWinVersionHelper::IsWindows8OrLater() const
{
    if (m_major_version > 6)
        return true;
    else if (m_major_version == 6 && m_minor_version >= 2)
        return true;
    else return false;
}

bool CWinVersionHelper::IsWindows10OrLater() const
{
    return m_major_version >= 10;
}

CCPUUsage.h:

#pragma once
#include <Pdh.h>
#include <PdhMsg.h>
#pragma comment(lib,"pdh.lib")

class CCPUUsage
{
public:
	CCPUUsage()
	{}

	~CCPUUsage()
	{}

	void SetUseCPUTimes(bool use_get_system_times);		//设置获取CPU利用率的方式,是通过GetSystemTimes还是Pdh
	int GetCPUUsage();

private:
	//int GetCPUUsageByGetSystemTimes();
	int GetCPUUsageByPdh();

private:
	bool m_use_get_system_times{ true };		//是否使用GetSysTime这个API来获取CPU利用率

	PDH_RAW_COUNTER m_last_rawData;//保存计算CPU使用率的上一次数据
	bool m_first_get_CPU_utility{ true };

	FILETIME m_preidleTime{};
	FILETIME m_prekernelTime{};
	FILETIME m_preuserTime{};

};

CCPUUsage.cpp:

#if 1
#include "CPUUsage.h"
#include "WinVersionHelper.h"
#include <iostream>

using namespace std;


void CCPUUsage::SetUseCPUTimes(bool use_get_system_times)
{
	if (m_use_get_system_times != use_get_system_times)
	{
		m_use_get_system_times = use_get_system_times;
		m_first_get_CPU_utility = true;
	}
}

int CCPUUsage::GetCPUUsage()
{
	//if (m_use_get_system_times)
	//	return GetCPUUsageByGetSystemTimes();
	//else
		return GetCPUUsageByPdh();
}

#if 0
int CCPUUsage::GetCPUUsageByGetSystemTimes()
{
	int cpu_usage{};
	FILETIME idleTime;
	FILETIME kernelTime;
	FILETIME userTime;
	GetSystemTimes(&idleTime, &kernelTime, &userTime);

	__int64 idle = CCommon::CompareFileTime2(m_preidleTime, idleTime);
	__int64 kernel = CCommon::CompareFileTime2(m_prekernelTime, kernelTime);
	__int64 user = CCommon::CompareFileTime2(m_preuserTime, userTime);

	if (kernel + user == 0)
	{
		cpu_usage = 0;
	}
	else
	{
		//(总的时间-空闲时间)/总的时间=占用cpu的时间就是使用率
		cpu_usage = static_cast<int>(abs((kernel + user - idle) * 100 / (kernel + user)));
	}
	m_preidleTime = idleTime;
	m_prekernelTime = kernelTime;
	m_preuserTime = userTime;

	return cpu_usage;
}
#endif

#include <iostream>
using namespace std;

int CCPUUsage::GetCPUUsageByPdh()
{
	int cpu_usage{};
	HQUERY hQuery;
	HCOUNTER hCounter;
	DWORD counterType;
	PDH_RAW_COUNTER rawData;

	PdhOpenQuery(NULL, 0, &hQuery);//开始查询
	const wchar_t* query_str{};
	if (g_winVerHelper.GetMajorVersion() >= 10)
		query_str = L"\\Processor Information(_Total)\\% Processor Utility";
	else
		query_str = L"\\Processor Information(_Total)\\% Processor Time";
	PdhAddCounter(hQuery, query_str, NULL, &hCounter);
	PdhCollectQueryData(hQuery);
	PdhGetRawCounterValue(hCounter, &counterType, &rawData);

	if (m_first_get_CPU_utility) {//需要获得两次数据才能计算CPU使用率
		cpu_usage = 0;
		m_first_get_CPU_utility = false;
	}
	else {
		PDH_FMT_COUNTERVALUE fmtValue;
		PdhCalculateCounterFromRawValue(hCounter, PDH_FMT_DOUBLE, &rawData, &m_last_rawData, &fmtValue);//计算使用率
		cpu_usage = fmtValue.doubleValue;//传出数据
		if (cpu_usage > 100)
			cpu_usage = 100;
	}
	m_last_rawData = rawData;//保存上一次数据
	PdhCloseQuery(hQuery);//关闭查询
	return cpu_usage;
}

#endif

main.cpp

#include "CPUUsage.h"
#include <iostream>

using namespace std;


int main() {
    CCPUUsage cpuUsage;
    cpuUsage.SetUseCPUTimes(false);
    while (1) {
        cout << cpuUsage.GetCPUUsage() << endl;
        Sleep(1000);
    }
}

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值