記事検索

検索ワードを入力してください。
Sky Tech Blog
Windows 11 の​ Thermal Zone デバイスから​温度を​取得する

Windows 11 の​ Thermal Zone デバイスから​温度を​取得する

Windows 11のデバイスマネージャーにある「ACPI温度管理ゾーン」デバイスからPC内の温度を取得する方法について説明しています。カーネルモードとユーザーモードでのデバイス一覧取得方法や、温度取得の具体的な手順を紹介しています。

Windows 11 のデバイスマネージャーの[システム]の配下にある、[ACPI温度管理ゾーン]というデバイスから、PC内の温度を取得する方法を紹介します。このデバイスは「Thermal Zone デバイス」と呼ばれるもので、PCによって構成が異なります。全く存在しないことがあったり、1つだけだったり、名前が異なったりします。Thermal Zone デバイスの一覧は以下の方法で取得できます。

カーネルモード

PWSTR pSymList = NULL;
IoGetDeviceInterfaces(&GUID_DEVICE_THERMAL_ZONE, NULL, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &pSymList);

で、シンボリックリンク(例:"\??\ACPI#ThermalZone#TZ02#{4afa3d51-74a7-11d0-be5e-00a0c9062857}")のマルチ文字列が取得できる("\0"で区切られて"\0\0"で終わる)。pSymListは ExFreePool で解放する。

ユーザーモード

HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVICE_THERMAL_ZONE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
for(int i=0 ; ; i++){
    SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
    devInterfaceData.cbSize = sizeof(devInterfaceData);
    SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVICE_THERMAL_ZONE, i, &devInterfaceData);
    PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)calloc(1, 4096);
    pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    SP_DEVINFO_DATA devInfoData = {0};
    devInfoData.cbSize = sizeof(devInfoData);
    SetupDiGetDeviceInterfaceDetail(hDevInfo, &devInterfaceData, pDetail, 4096, NULL, &devInfoData);

で、pDetail->DevicePathにシンボリックリンク(例:"\\?\ACPI#ThermalZone#TZ02#{4afa3d51-74a7-11d0-be5e-00a0c9062857}")が取得できる。hDevInfoは SetupDiDestroyDeviceInfoList で解放する。pDetail は free で解放する。

カーネルモードとユーザーモードでは、シンボリックリンクの最初の部分が異なります。カーネルモードとユーザーモードでリンク名をやり取りする場合は、自前で文字列の置き換えを行ってください。

カーネルモード

*\??\*{.c}ACPI#ThermalZone#TZ02#{4afa3d51-74a7-11d0-be5e-00a0c9062857}

ユーザーモード

*\\?\*{.c}ACPI#ThermalZone#TZ02#{4afa3d51-74a7-11d0-be5e-00a0c9062857}

こちらで試した限りでは、温度取得はカーネルモード、つまりドライバ側からしか取得できませんでした。ドライバ内にて、デバイスオブジェクトにIRP_MJ_DEVICE_CONTROLを送ることによって、温度を取得します。デバイスオブジェクトにIRP_MJ_DEVICE_CONTROLを送る方法は、以下のステップで行います。

  • IoGetDeviceObjectPointer にシンボリックリンク名(例:"\??\ACPI#ThermalZone#TZ02#{4afa3d51-74a7-11d0-be5e-00a0c9062857}")を指定してPDEVICE_OBJECTを取得。
  • IoBuildDeviceIoControlRequest に、後述のIOCTLコードと、NonPagedPoolに確保したKEVENTを指定して、IRPを作成する。
  • IoCallDriverにIRPを指定して実行。
  • KeWaitForSingleObjectで、指定したKEVENTのシグナルを待つ。

注意すべき点は、2のNonPagedPoolに確保したKEVENTを指定することです。 ACPIドライバの中には、完了ルーチンをDISPATCH_LEVELで呼び出すものもあるので、安全のためにNonPagedPoolに確保したイベントオブジェクトを指定してください。

IRP_MJ_DEVICE_CONTROLで送るIOCTLコードは3つの手法があります。どの手法でも同じ温度が取得できますが、デバイスによってサポートしている手法が異なるようなので、全部試してみることをお勧めします。

手法1:ACPIメソッド"_TMP"を​使う。

// コントロールコード
IOCTL_ACPI_EVAL_METHOD

// 入力バッファ
ACPI_EVAL_INPUT_BUFFER stInputBuf = {0};
stInputBuf.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
RtlCopyMemory(stInputBuf.MethodName, "_TMP", 4);

// 出力バッファ
ACPI_EVAL_OUTPUT_BUFFER stOutputBuf = {0};

stOutputBuf.Argument[0].Argumentに温度が入って返されます。

手法2:IOCTL_THERMAL_READ_TEMPERATUREを​使う。

// コントロールコード
IOCTL_THERMAL_READ_TEMPERATURE

// 入力バッファ
THERMAL_WAIT_READ waitRead = {0};
waitRead.Timeout = (ULONG)0;

// 出力バッファ
ULONG ulTemp = 0;

ulTemp に温度が入って返されます。

手法3:IOCTL_THERMAL_QUERY_INFORMATIONを​使う。

// コントロールコード
IOCTL_THERMAL_QUERY_INFORMATION

// 入力バッファ
なし

// 出力バッファ
typedef struct _THERMAL_INFORMATION_EX{
    ULONG ThermalStamp;
    ULONG ThermalConstant1;
    ULONG ThermalConstant2;
    ULONG SamplingPeriod;
    ULONG CurrentTemperature;
    ULONG PassiveTripPoint;
    ULONG ThermalStandbyTripPoint;
    ULONG CriticalTripPoint;
    UCHAR ActiveTripPointCount;
    UCHAR PassiveCoolingDevicesPresent;
    ULONG ActiveTripPoint[10];
    ULONG S4TransitionTripPoint;
    ULONG MinimumThrottle;
    ULONG OverThrottleThreshold;
    ULONG PollingPeriod;
}THERMAL_INFORMATION_EX, *PTHERMAL_INFORMATION_EX;
THERMAL_INFORMATION_EX stThrmInfo = {0};

ネット上でよく見かけるTHERMAL_INFORMATION_EX 構造体ではサイズが足りずに、クラッシュします。 Windows 11 24H2 では上記のフィールドとサイズになっていました。CurrentTemperatureに温度が入って返されます。

すべての手法で取得できる温度を、摂氏(℃)に変換するには、Temperature / 10.0 - 273.15してください。


\シェアをお願いします!/
  • X
  • Facebook
  • LINE
キャリア採用募集中!

入社後にスキルアップを目指す若手の方も、ご自身の経験を幅広いフィールドで生かしたいベテランの方も、お一人おひとりの経験に応じたキャリア採用を行っています。

Sky株式会社のソフトウェア開発や製品、採用に関するお問い合わせについては、下記のリンクをご確認ください。
お問い合わせ
ホーム