Получить температуру процессора

Я хочу получить температуру процессора. Ниже показано, что я сделал с помощью C ++ и WMI. Я читаю MSAcpi_ThermalZoneTemperature, но он всегда один и тот же, и это совсем не температура процессора.

Есть ли способ получить реальную температуру процессора без необходимости писать драйверы? Или есть какие-нибудь библиотеки, которые я могу использовать? Заранее спасибо.

#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;
}

person Johnny Mnemonic    schedule 26.04.2014    source источник
comment
Вы сравнивали свою температуру с помощью какого-либо программного обеспечения для мониторинга (superuser.com/a/395437/15484)? А как насчет преобразования Кельвина-Цельсия? (PS: вы можете повторно использовать драйвер из RealTemp или другого проекта)   -  person osgx    schedule 26.04.2014
comment
Я делаю преобразование (temp / 10 - 273.15), но результат всегда 70,05 и Core Temp показывает другую температуру.   -  person Johnny Mnemonic    schedule 27.04.2014
comment
Вы знакомы с сайтом openhardwaremonitor.org?   -  person Rotem    schedule 19.07.2017
comment
Возможный дубликат Как узнать температуру процессора?   -  person huysentruitw    schedule 01.06.2018
comment
@Housy не дубликат, потому что этот вопрос определенно касается выполнения этого через Windows API, а тот, на который вы ссылаетесь, касается выполнения этого через управляемый код.   -  person amn    schedule 17.09.2018
comment
Это дубликат. Предлагаемые ответы в связанном вопросе указывают либо на WMI (который доступен через Windows API), либо на OpenHardwareMonitor (который является открытым исходным кодом и внутренне вызывает Windows API), для этого просто нужно немного покопаться.   -  person huysentruitw    schedule 17.09.2018


Ответы (4)


Ссылка на исходный код OpenHardwareMonitorLib, представленная в ответе Томера, показывает, что должно произойти на низком уровне, чтобы прочитать эту информацию из разных источников. типы процессоров. Например, класс 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;

Они взяты прямо из документации Intel, например Мониторинг CPU с помощью раздел 16 «Прямой доступ к MSR»). Они также могут быть задокументированы в Руководстве разработчика программного обеспечения Intel, но я не проверял.

OpenHardwareMonitorLib использует Rdmsr и RdmsrTx для получения значений температуры из интересующих MSR.

соответствующий код AMD выглядит так, как будто он получает аналогичную информацию. регистра PCI. У AMD будет где-нибудь эквивалентная документация, в которой это будет определено.

В обоих случаях это по определению то, как оборудование предоставляет информацию о своих датчиках температуры. Вы можете использовать подобную библиотеку, и она будет делать это под капотом, или вы можете написать собственный эквивалентный код.

person Aaron Altman    schedule 01.08.2019
comment
Обратите внимание, что rdmsr требуется драйвер ядра, что невозможно сделать из кода пользовательского режима. - person josh poley; 01.08.2019

По правде говоря, это зависит от оборудования.

Библиотека, которая работает на большинстве аппаратных средств, - это OpenHardwareMonitorLib. К сожалению, у него нет документации и фактически не существует как независимая часть программного обеспечения. Это часть программного обеспечения с открытым исходным кодом под названием Open Hardware Monitor. это сделано в .NET C Sharp и, конечно, работает только для Windows. К счастью, вы можете получить его как DLL, а графический интерфейс полностью отделен от фактического внутреннего интерфейса, которым является OpenHardwareMonitorLib.

Прочтите этот пост о том, как использовать его из C ++

Как вызвать Библиотека C # из Native C ++ (с использованием C ++ \ CLI и IJW)

Так что, учитывая, что у него нет документов, с этим может быть немного сложно работать. Прочитав источник некоторое время, я делаю следующее:

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;

Подтверждено, что этот код #C успешно определяет температуру процессора Intel Haswell в градусах Цельсия. Скорее всего, он будет работать с большинством других процессоров AMD и Intel. OpenHardwareMonitorLib.dll необходим. Вы можете скомпилировать его из источника

С помощью этой библиотеки вы можете получить много другой информации о системе.

Обратите внимание, что ЦП пользователя может иметь несколько датчиков температуры. Например, датчик температуры для каждой жилы, поэтому не всегда берите последний, как в примере выше.

Удачи.

person tomer zeitune    schedule 29.07.2019

Упомянутые классы WMI не работали для меня в последней версии Windows 10. На моем ноутбуке Dell я мог получить температуру процессора в градусах Цельсия здесь:

ROOT_CIMV2\Win32_PerfFormattedData_Counters_ThermalZoneInformation\HighPrecisionTemperature
person Carsten    schedule 06.03.2021

WMI имеет класс Win32_TemperaProbe:

http://msdn.microsoft.com/en-us/library/aa394493%28VS.85%29.aspx

Попробуйте вместо MSAcpi_ThermalZoneTemperature

обн.

Итак, я попробовал код страницы примера MS здесь. Он показывает способ получения информации из классов WMI.

Обычно он такой же, как у вас, но с именем класса и имени свойства. Так что измените строку

BSTR query = SysAllocString(L"SELECT * FROM MSAcpi_ThermalZoneTemperature");

to

BSTR query = SysAllocString(L"SELECT * FROM Win32_TemperatureProbe");

или к родительскому классу

BSTR query = SysAllocString(L"SELECT * FROM CIM_TemperatureSensor");

затем измените имя свойства на «CurrentReading»

Но, к сожалению, код для получения этого параметра может быть не реализован в драйверах материнской платы или драйверах MS. В этом случае результат типа VARIANT будет установлен в NULL.

person Monster    schedule 26.04.2014
comment
Из этих документов, Показания в реальном времени для свойства CurrentReading не могут быть извлечены из таблиц SMBIOS. По этой причине текущие реализации WMI не заполняют свойство CurrentReading. Поскольку op ищет текущую температуру процессора, я считаю, что для этого класса WMI потребуется рабочее свойство CurrentReading для выполнения этой работы. - person cf stands with Monica; 26.04.2014
comment
Это работает для тебя, Монстр? У меня это не работает, и, как сказал взломщик компьютеров, согласно документации CurrentReading не заполнен. - person Johnny Mnemonic; 27.04.2014
comment
Да, это работает. Во всяком случае, это тоже реализовано в классе CIM_TemperaSensor, попробуйте. - person Monster; 27.04.2014
comment
Я получаю 0x80041010 ошибку, когда звоню IEnumWbemClassObject::Next(). Кто-нибудь заставил его предложения работать? - person c00000fd; 23.02.2017