C++ 获取 CPU 温度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23314886/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get CPU Temperature
提问by Johnny Mnemonic
I want to get the CPU temperature. Below is what I've done using C++ and WMI. I'm reading MSAcpi_ThermalZoneTemperature, but it's always the same and it's not the CPU temperature at all.
我想获取 CPU 温度。下面是我使用 C++ 和 WMI 所做的。我正在阅读 MSAcpi_ThermalZoneTemperature,但它始终相同,根本不是 CPU 温度。
Is there any way to get the real temperature of the CPU without having to write drivers? Or are there any libs which I can use? Thank you in advance.
有没有什么办法不用写驱动就可以得到CPU的真实温度?或者有没有我可以使用的库?先感谢您。
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
HRESULT GetCpuTemperature(LPLONG pTemperature)
{
if (pTemperature == NULL)
return E_INVALIDARG;
*pTemperature = -1;
HRESULT ci = CoInitialize(NULL);
HRESULT hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (SUCCEEDED(hr))
{
IWbemLocator *pLocator;
hr = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLocator);
if (SUCCEEDED(hr))
{
IWbemServices *pServices;
BSTR ns = SysAllocString(L"root\WMI");
hr = pLocator->ConnectServer(ns, NULL, NULL, NULL, 0, NULL, NULL, &pServices);
pLocator->Release();
SysFreeString(ns);
if (SUCCEEDED(hr))
{
BSTR query = SysAllocString(L"SELECT * FROM MSAcpi_ThermalZoneTemperature");
BSTR wql = SysAllocString(L"WQL");
IEnumWbemClassObject *pEnum;
hr = pServices->ExecQuery(wql, query, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum);
SysFreeString(wql);
SysFreeString(query);
pServices->Release();
if (SUCCEEDED(hr))
{
IWbemClassObject *pObject;
ULONG returned;
hr = pEnum->Next(WBEM_INFINITE, 1, &pObject, &returned);
pEnum->Release();
if (SUCCEEDED(hr))
{
BSTR temp = SysAllocString(L"CurrentTemperature");
VARIANT v;
VariantInit(&v);
hr = pObject->Get(temp, 0, &v, NULL, NULL);
pObject->Release();
SysFreeString(temp);
if (SUCCEEDED(hr))
{
*pTemperature = V_I4(&v);
}
VariantClear(&v);
}
}
}
if (ci == S_OK)
{
CoUninitialize();
}
}
}
return hr;
}
int main(int argc, char **argv)
{
LONG temp;
GetCpuTemperature(&temp);
printf("temp=%lf\n", ((double)temp / 10 - 273.15));
getc(stdin);
return 0;
}
回答by tomer zeitune
Truth be told, it depends on the hardware.
说实话,这取决于硬件。
A library that works on most hardware is OpenHardwareMonitorLib, unfortunately, it has no documentation and actually doesn't really exist as an independent piece of software. it's part of an open-source software named "Open Hardware Monitor". it's done in .NET C Sharp and of course, only works for Windows. fortunately you can get it as a DLL, and the GUI is completely separated from the actual backend which is the OpenHardwareMonitorLib.
一个适用于大多数硬件的库是 OpenHardwareMonitorLib,不幸的是,它没有文档,实际上并不是作为一个独立的软件而存在的。它是名为“Open Hardware Monitor”的开源软件的一部分。它是在 .NET C Sharp 中完成的,当然,仅适用于 Windows。幸运的是,您可以将其作为 DLL 获取,并且 GUI 与实际的后端 OpenHardwareMonitorLib 完全分离。
Read this post on how to use it from C++
阅读这篇关于如何从 C++ 使用它的文章
How to call a C# library from Native C++ (using C++\CLI and IJW)
如何从本机 C++ 调用 C# 库(使用 C++\CLI 和 IJW)
So considering it has no docs this can be a bit hard to work with. After reading the source for a while this is my take:
因此,考虑到它没有文档,这可能有点难以使用。阅读源代码一段时间后,这是我的看法:
using OpenHardwareMonitor.Hardware;
...
float? cpu_temperature_celcius = null;
Computer computer= new Computer();
computer.CPUEnabled = true;
computer.Open();
foreach (IHardware hardware in computer.Hardware)
if (hardware.HardwareType == HardwareType.CPU)
foreach (ISensor sensor in hardware.Sensors)
if (sensor.SensorType == SensorType.Temperature)
cpu_temperature_celcius = sensor.Value;
This #C code is verified to get the temperature of an Intel Haswell CPU in Celcius and will most likely work for most other CPUs from AMD and Intel. OpenHardwareMonitorLib.dll is needed. You can compile it from source
此#C 代码经过验证,可以获取 Celcius 中 Intel Haswell CPU 的温度,并且很可能适用于 AMD 和 Intel 的大多数其他 CPU。需要 OpenHardwareMonitorLib.dll。您可以从源代码编译它
You can get a lot of other information about the system with this library.
您可以使用此库获取有关系统的许多其他信息。
Note that the CPU of the user can have multiple temperature sensors. For example a temperature sensor for every core, so don't always take the last one as I did in the example above.
请注意,用户的 CPU 可以有多个温度传感器。例如,每个核心都有一个温度传感器,所以不要像我在上面的例子中那样总是使用最后一个。
Good luck.
祝你好运。
回答by Aaron Altman
The link to source for OpenHardwareMonitorLib provided in Tomer's answerillustrates what has to happen at a low level to read this information out of different types of CPUs. For example, the IntelCPUclass defines some model-specific registers:
Tomer 的回答中提供的 OpenHardwareMonitorLib 源链接说明了从不同类型的 CPU 读取此信息必须在低级别发生的事情。例如,IntelCPU类定义了一些特定于模型的寄存器:
private const uint IA32_THERM_STATUS_MSR = 0x019C; private const uint IA32_TEMPERATURE_TARGET = 0x01A2; private const uint IA32_PERF_STATUS = 0x0198; private const uint MSR_PLATFORM_INFO = 0xCE; private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1; private const uint MSR_RAPL_POWER_UNIT = 0x606; private const uint MSR_PKG_ENERY_STATUS = 0x611; private const uint MSR_DRAM_ENERGY_STATUS = 0x619; private const uint MSR_PP0_ENERY_STATUS = 0x639; private const uint MSR_PP1_ENERY_STATUS = 0x641;
private const uint IA32_THERM_STATUS_MSR = 0x019C; private const uint IA32_TEMPERATURE_TARGET = 0x01A2; private const uint IA32_PERF_STATUS = 0x0198; private const uint MSR_PLATFORM_INFO = 0xCE; private const uint IA32_PACKAGE_THERM_STATUS = 0x1B1; private const uint MSR_RAPL_POWER_UNIT = 0x606; private const uint MSR_PKG_ENERY_STATUS = 0x611; private const uint MSR_DRAM_ENERGY_STATUS = 0x619; private const uint MSR_PP0_ENERY_STATUS = 0x639; private const uint MSR_PP1_ENERY_STATUS = 0x641;
These are straight out of Intel's docs like CPU Monitoring with DTS/PECI(section 16 "Direct MSR Access"). They may also be documented in the Intel Software Developer Manual but I haven't checked.
这些直接来自 Intel 的文档,例如CPU Monitoring with DTS/PECI(第 16 节“直接 MSR 访问”)。它们也可能记录在英特尔软件开发人员手册中,但我没有检查。
The OpenHardwareMonitorLib uses Rdmsr and RdmsrTx to get temperature values out of the MSRs of interest.
OpenHardwareMonitorLib 使用 Rdmsr 和 RdmsrTx 从感兴趣的 MSR 中获取温度值。
The corresponding AMD codelooks like it gets similar info out of a PCI register. AMD will have equivalent documentation somewhere that will define this.
将相应的AMD代码看起来像它得到了一个PCI寄存器的类似信息。AMD 将在某处提供等效的文档来定义这一点。
In both cases these are, by definition, how the hardware exposes information about its temperature sensors. You can use a library like this and it'll be doing this under the hood, or you can write equivalent code of your own.
在这两种情况下,根据定义,这些都是硬件如何公开有关其温度传感器的信息。您可以使用这样的库,它会在后台执行此操作,或者您可以编写自己的等效代码。
回答by Monster
WMI has the Win32_TemperatureProbe class:
WMI 具有 Win32_TemperatureProbe 类:
http://msdn.microsoft.com/en-us/library/aa394493%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa394493%28VS.85%29.aspx
Try it instead of MSAcpi_ThermalZoneTemperature
试试它而不是 MSAcpi_ThermalZoneTemperature
upd.
更新。
So, I tried the code from MS example page here. It shows the way to retrieve information from WMI classes.
所以,我在这里尝试了 MS 示例页面中的代码。它显示了从 WMI 类检索信息的方法。
It's generally the same as yours but the class name and property name. So change the line
它通常与您的相同,但类名和属性名不同。所以换行
BSTR query = SysAllocString(L"SELECT * FROM MSAcpi_ThermalZoneTemperature");
to
到
BSTR query = SysAllocString(L"SELECT * FROM Win32_TemperatureProbe");
or to it's parent class
或者它的父类
BSTR query = SysAllocString(L"SELECT * FROM CIM_TemperatureSensor");
then change the property name to "CurrentReading"
然后将属性名称更改为“CurrentReading”
But unfortunatelly the code for retrieving this parameter may be not implemented in motherboard drivers or MS drivers. In that case the result of VARIANT type will be set to NULL.
但不幸的是,主板驱动程序或 MS 驱动程序中可能没有实现用于检索此参数的代码。在这种情况下,VARIANT 类型的结果将被设置为 NULL。