【WIN32】获取CPU状态

40 篇文章 6 订阅


温故而知新,可以为师矣

在检查自己过往代码的时候,又找到了一篇可以拿得出手的文章,今天就讲讲“如何获取Windows CPU”!

使用C++获取CPU信息的方式不止一种,目前我知识面可以覆盖到的方法有三种?

  1. 使用WMI查询
  2. 使用Win32提供的API查询
  3. 使用注册表查询

这篇文章不分重点,只讲方式,说一下这三种方式。


使用WMI查询

不知道WMI的可以看这个百度百科👉WMI(系统插件)_百度百科

这里提供我整理的两种WMI查询接口:

  • 单个信息查询
/*
* @fn           GetSingleItemInfo
* @brief        根据查询语句获得一个类成员
* @param[in]    ClassName:库名如:“Win32_Processor”
				ClassMember:项目名如:“SerialNumber”
* @param[out]   
* @return       
* @author       Fuel_Ming
*/
BOOL GetSingleItemInfo( __in const wstring &ClassName,__in const wstring &ClassMember,__out wstring &RetValue )
{
	USES_CONVERSION;
	CComBSTR query("SELECT * FROM ");
	CString	CstrRetValue;

	VARIANT    vtProp;
	ULONG      uReturn;
	HRESULT    hr;
	BOOL       bRet = FALSE;

	InitWmi();

	if (NULL != m_pWbemSvc)
	{
		//查询类ClassName中的所有字段,保存到m_pEnumClsObj中
		query+=CComBSTR(ClassName.c_str());
		hr=m_pWbemSvc->ExecQuery(CComBSTR("WQL"), query, WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY,
			0,&m_pEnumClsObj);

		if( m_pEnumClsObj == NULL )
		{
			WriteError(_T("m_pEnumClsObj == NULL : %x"), hr);
			goto END;
		}

		if (SUCCEEDED(hr))
		{
			//初始化vtProp值
			VariantInit(&vtProp);
			uReturn = 0;

			//返回从当前位置起的第一个对象到m_pWbemClsObj中
			hr=m_pEnumClsObj->Next( WBEM_INFINITE, 1, &m_pWbemClsObj, &uReturn);
			if( m_pWbemClsObj == NULL )
			{
				WriteError(_T("m_pWbemClsObj == NULL : %x"), hr);
				goto END;
			}

			if(SUCCEEDED(hr)&&uReturn>0)
			{
				//从m_pWbemClsObj中找出ClassMember标识的成员属性值,并保存到vtProp变量中
				hr=m_pWbemClsObj->Get(CComBSTR(ClassMember.c_str()),0,&vtProp,0,0);
				if (SUCCEEDED(hr))
				{
					VariantToString(&vtProp,CstrRetValue);
					RetValue = CstrRetValue.GetString();
					VariantClear(&vtProp);//清空vtProp
					bRet = TRUE;
				}
			}
		}
	}
END:
	ReleaseWmi();
	return bRet;

}
  • 按组查询
/*
* @fn           GetGroupItemInfo
* @brief        根据查询语句获得一个类的多个成员
* @param[in]    ClassName:  库名如:“Win32_Processor”
				ClassMember:项目名如:“SerialNumber”
				n: 成员个数
* @param[out]   chRetValue: 返回获得的成员
* @return       
*               
* @detail      Example: 
				CString strRetValue;
				CString [] strClassMem = 
				{_T("Caption"),_T("CurrentClockSpeed"),_T("DeviceID"),_T("Manufacturer"),_T("Manufacturer")};
				GetGroupItemInfo(_T("Win32_Processor"),strClassMem,5,strRetValue);
* @author       Fuel_Ming
*/
BOOL CWmiIface::GetGroupItemInfo(__in const wstring &ClassName, __in const vector<wstring> &vectClassMember, __out std::vector<wstring> &vecRetValue)
{
	USES_CONVERSION;

	CComBSTR query("SELECT * FROM ");
	CString result,info;
	VARIANT vtProp;
	ULONG uReturn;
	HRESULT hr;
	int i;
	int n = vectClassMember.size();
	BOOL bRet = FALSE;

	InitWmi();

	if (NULL  != m_pWbemSvc)
	{
		query+=CComBSTR(ClassName.c_str());
		hr=m_pWbemSvc->ExecQuery(CComBSTR("WQL"),query,WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY,0,&m_pEnumClsObj);
		if (SUCCEEDED(hr))
		{
			VariantInit(&vtProp); //初始化vtProp变量
			if(m_pEnumClsObj)
			{
				Sleep(10);
				uReturn=0;
				hr=m_pEnumClsObj->Next(WBEM_INFINITE,1,&m_pWbemClsObj,&uReturn);
				if( m_pWbemClsObj == NULL )
				{
					WriteError(_T("m_pServer == NULL : %x"), hr);
					goto END;
				}

				
				if (SUCCEEDED(hr) &&uReturn>0)
				{
					for(i = 0; i < n; ++i)
					{
						CString chTemp = TEXT("");
						hr=m_pWbemClsObj->Get(CComBSTR(vectClassMember[i].c_str()),0,&vtProp,0,0);
						if (SUCCEEDED(hr))
						{
							VariantToString(&vtProp,info);
							chTemp = info;
							VariantClear(&vtProp);
							bRet = TRUE;
						}
						vecRetValue.push_back(chTemp.GetString());
					}
				}
			}
		}
	}

END:	

	ReleaseWmi();

	return bRet;
}

要使用WMI得先初始化接口:

HRESULT InitWmi()
{
	HRESULT hr;

	// 1、初始化COM组件
	hr = CoInitializeEx(0, COINIT_MULTITHREADED);
	if (SUCCEEDED(hr) || RPC_E_CHANGED_MODE == hr)
	{
	    m_bInitialize = TRUE;
		hr = CoInitializeSecurity(
			NULL, 
			-1,                          
			NULL,                        
			NULL,                        
			RPC_C_AUTHN_LEVEL_DEFAULT,   
			RPC_C_IMP_LEVEL_IMPERSONATE, 
			NULL,                        
			EOAC_NONE,                   
			NULL                         
			);
		hr = CoCreateInstance(
			CLSID_WbemLocator,
			0, 
			CLSCTX_INPROC_SERVER, 
			IID_IWbemLocator, (LPVOID *) &m_pWbemLoc);

		hr = m_pWbemLoc->ConnectServer(
			_bstr_t(L"ROOT\\CIMV2"), 
			NULL,                    
			NULL,                    
			0,                       
			NULL,                    
			0,                       
			0,                       
			&m_pWbemSvc
		);

		if (FAILED(hr))
		{
			WriteError(_T("IWbemLocator::ConnectServer is failed. hr=%x"), hr);
			goto END;
		}

		hr = CoSetProxyBlanket(
			m_pWbemSvc,
			RPC_C_AUTHN_WINNT,           
			RPC_C_AUTHZ_NONE,            
			NULL,                        
			RPC_C_AUTHN_LEVEL_CALL,      
			RPC_C_IMP_LEVEL_IMPERSONATE, 
			NULL,                        
			EOAC_NONE                    
			);
    	if (FAILED(hr))	
    	{
    		WriteError(_T("CoSetProxyBlanket is failed. hr=%x"), hr);
    		goto END;
    	}
	}


	return(hr);

END:
	if(FAILED(hr))
	{
		ReleaseWmi();
	}
	
	return(hr);
}

用完记得释放:

HRESULT ReleaseWmi()
{
	HRESULT hr;

	if (NULL != m_pWbemSvc)
	{
		hr = m_pWbemSvc->Release();
		m_pWbemSvc = NULL;
	}
	if (NULL != m_pWbemLoc)
	{
		hr = m_pWbemLoc->Release();
		m_pWbemLoc = NULL;
	}
	if (NULL != m_pWbemClsObj)
	{
		hr = m_pWbemClsObj->Release();
		m_pWbemClsObj = NULL;
	}
	if (NULL != m_pEnumClsObj)
	{
		hr = m_pEnumClsObj->Release();
		m_pEnumClsObj = NULL;
	}
    if(m_bInitialize)
    {
    	::CoUninitialize();
	    m_bInitialize = FALSE;    
    }
	return(hr);
}

上述接口使用到的辅助函数:

  1. 变量转字符串:
void CWmiIface::VariantToString(__in const LPVARIANT pVar,__out CString &chRetValue) const
{
	USES_CONVERSION;

	CComBSTR HUGEP* pBstr;
	BYTE HUGEP* pBuf;
	LONG low,high,i;
	HRESULT hr;

	switch(pVar->vt)
	{
	case VT_BSTR:
		{
			chRetValue=W2T(pVar->bstrVal);
		}
		break;
	case VT_BOOL:
		{
			if(VARIANT_TRUE==pVar->boolVal)
				chRetValue="1";
			else
				chRetValue="0";
		}
		break;
	case VT_I4:
		{
			chRetValue.Format(_T("%d"),pVar->lVal);
		}
		break;
	case VT_UI1:
		{
			chRetValue.Format(_T("%d"),pVar->bVal);
		}
		break;
	case VT_UI4:
		{
			chRetValue.Format(_T("%d"),pVar->ulVal);
		}
		break;

	case VT_BSTR|VT_ARRAY:
		{
			hr=SafeArrayAccessData(pVar->parray,(void HUGEP**)&pBstr);
			hr=SafeArrayUnaccessData(pVar->parray);
			chRetValue=W2T(pBstr->m_str);
		}
		break;

	case VT_I4|VT_ARRAY:
		{
			SafeArrayGetLBound(pVar->parray,1,&low);
			SafeArrayGetUBound(pVar->parray,1,&high);

			hr=SafeArrayAccessData(pVar->parray,(void HUGEP**)&pBuf);
			hr=SafeArrayUnaccessData(pVar->parray);
			CString strTmp;
			high=min(high,MAX_PATH*2-1);
			for(i=low;i<=high;++i)
			{
				strTmp.Format(_T("%02X"),pBuf[i]);
				chRetValue+=strTmp;
			}
		}
		break;
	default:
		break;
	}
}

通过Wmi查询CPU信息

以下仅作为示例,查询信息的子段可以去这里查看👉Win32_Processor class - Win32 apps | Microsoft Docs

// 5. 获取CPU信息|CPU频率
	vecstrRet.clear();
	vectQueryClassKey.push_back(_T("Description"));
	vectQueryClassKey.push_back(_T("MaxClockSpeed"));
	bRet = cwmi.GetGroupItemInfo(_T("Win32_Processor"), vectQueryClassKey, vecstrRet);
	if(bRet)
	{
		CString csMaxClockSpeed;
		csMaxClockSpeed.Format(_T("%s MHz"), vecstrRet[1].c_str());

		_tcsncpy_s(stuDetect.strCPU,	ArraySize(stuDetect.strCPU),	vecstrRet[0].c_str(),	ArraySize(stuDetect.strCPU) - 1);
		_tcsncpy_s(stuDetect.strCPUFreq,ArraySize(stuDetect.strCPUFreq),csMaxClockSpeed.GetString(),ArraySize(stuDetect.strCPUFreq) - 1);
	}

使用Win32提供的API查询

直接查询Win32文档可以找到相关接口:

以获取CPU数量为例:

int getCPUNum()
{
	SYSTEM_INFO si;
	GetSystemInfo(&si);
	return si.dwNumberOfProcessors;
}

其中SYSTEM_INFO结构体如下所示,包含了CPU的各项信息:

typedef struct _SYSTEM_INFO {
  union {
    DWORD dwOemId;
    struct {
      WORD wProcessorArchitecture;
      WORD wReserved;
    } DUMMYSTRUCTNAME;
  } DUMMYUNIONNAME;
  DWORD     dwPageSize;
  LPVOID    lpMinimumApplicationAddress;
  LPVOID    lpMaximumApplicationAddress;
  DWORD_PTR dwActiveProcessorMask;
  DWORD     dwNumberOfProcessors;
  DWORD     dwProcessorType;
  DWORD     dwAllocationGranularity;
  WORD      wProcessorLevel;
  WORD      wProcessorRevision;
} SYSTEM_INFO, *LPSYSTEM_INFO;

使用注册表查询(CPU)

查看注册表HKLM\HARDWARE\DESCRIPTION\路径,可以看到微软的相关解释是:

The System subkey stores data collected by the Windows 2000 hardware recognizer. It includes information about the BIOS, processors, and bus architecture. The System subkey is recreated each time the system starts.

在该注册表路径下,存在ProcessorNameString项,即CPU信息。

下述代码实现了通过该注册表获取该CPU信息的功能:

void getCpuInfo(__out CString &chProcessorName)  
{
	CString strPath=_T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");	//注册表子键路径  
	CRegKey regkey;			//定义注册表类对象  
	LONG	lResult;		//LONG型变量-反应结果
	WCHAR chCPUName[MAX_KEY_LENGTH] = {0};  
	DWORD dwSize = MAX_KEY_LENGTH;

	lResult=regkey.Open(HKEY_LOCAL_MACHINE,LPCTSTR(strPath),KEY_ALL_ACCESS); //打开注册表键  
	if (lResult!=ERROR_SUCCESS)  
	{
		WriteError(_T("Open Reg Key Failed, Key=%s"), strPath.GetString());
		return;  
	}

	//获取ProcessorNameString字段值  
	if (ERROR_SUCCESS == regkey.QueryStringValue(_T("ProcessorNameString"),chCPUName,&dwSize))  
	{  
		chProcessorName = chCPUName;  
	} 
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧恩意

如有帮助,感谢打赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值