如何获取CPU温度?

71

我需要收集一些关于系统的信息用于我正在开发的应用程序。使用C#可以轻松获取可用内存和CPU负载,但是CPU温度不那么容易获取。我尝试使用WMI,但是无法获取任何信息。

Win32_TemperatureProbe

或者

MSAcpi_ThermalZoneTemperature

我该怎么做?我想知道像SiSoftware Sandra这样的监控程序是如何获取那些信息的...

以下是该类的代码:

public class SystemInformation
{
    private System.Diagnostics.PerformanceCounter m_memoryCounter;
    private System.Diagnostics.PerformanceCounter m_CPUCounter;

    public SystemInformation()
    {
        m_memoryCounter = new System.Diagnostics.PerformanceCounter();
        m_memoryCounter.CategoryName = "Memory";
        m_memoryCounter.CounterName = "Available MBytes";

        m_CPUCounter = new System.Diagnostics.PerformanceCounter();
        m_CPUCounter.CategoryName = "Processor";
        m_CPUCounter.CounterName = "% Processor Time";
        m_CPUCounter.InstanceName = "_Total";
    }

    public float GetAvailableMemory()
    {
        return m_memoryCounter.NextValue();
    }

    public float GetCPULoad()
    {
        return m_CPUCounter.NextValue();
    }

    public float GetCPUTemperature()
    {
        //...
        return 0;
    }
}

如果您愿意支付费用,我会建议您查看http://www.cpuid-pro.com。如果我没记错的话,这是与“z-cpu”使用相同的库。 - Peter
9个回答

78
对于可能经过这里的其他人,也许可以看一下:http://openhardwaremonitor.org/ 点击链接后,你可能会想:“嘿,这是一个应用程序,所以它被删除了。问题是如何从C#代码中实现这个功能,而不是找一个能告诉我温度的应用程序...” 这就显示出你不愿意花足够的时间阅读“Open Hardware Monitor”的内容。
他们还包括一个数据接口。以下是描述: 数据接口 Open Hardware Monitor将所有传感器数据发布到WMI(Windows管理规范)。这使得其他应用程序也可以读取和使用传感器信息。接口的初步文档可以在这里找到:点击此处
当你下载它时,其中包含了OpenHardwareMonitor.exe应用程序,而你并不需要那个。它还包含了OpenHardwareMonitorLib.dll,而你正需要的就是它。
这基本上,如果不是100%,只是WinRing0 API的一个包装器,如果你愿意,你可以选择自己包装它。
我自己从一个C#应用程序中尝试过这个,它可以工作。虽然它还处于测试阶段,但似乎相当稳定。它也是开源的,所以它可能是一个很好的起点。
更新截至2023年6月26日
如评论中所指出,看起来该项目不再维护,但在这里有一个维护的分支:

https://github.com/LibreHardwareMonitor/LibreHardwareMonitor


1
你能提供关于OpenHardware Lib使用的任何文档链接吗?我似乎找不到如何在我的项目中使用它。 - Chris Watts
很遗憾,我只是使用了普通的“发现”来找到我需要的东西...但你有什么问题吗?...在最基本的层面上,它是实例化“计算机”类,然后从那里开始工作...(例如,计算机-> IHardware-> ISensors) 或者从他们的SVN存储库中下载源代码并尝试弄清楚他们自己的GUI,就个人而言,我没有遇到太大的问题,只是发现了一些东西,但如果你缺少某些特定的东西,也许可以这样做? - Jens
而且,通过研究他们的GUI,我是指作为启发灵感的来源,以了解如何访问各种不同的传感器等等...然后在您自己的项目中复制该使用方式。 - Jens
这真的很有帮助。在这里找到了比我寻找的还要多得多的东西。谢谢。 - Ivan Peric
那个项目已经停止了。LibreHardwareMonitor是它的活跃分支。 - Carsten
显示剩余2条评论

40

使用WMI方法在C#中确实可以很容易地读取CPU温度。

为了获取摄氏温度,我创建了一个包装器,将WMI返回的值转换并封装成易于使用的对象。

请记得在Visual Studio中添加对System.Management.dll的引用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;

namespace RCoding.Common.Diagnostics.SystemInfo
{
    public class Temperature
    {
        public double CurrentValue { get; set; }
        public string InstanceName { get; set; }
        public static List<Temperature> Temperatures
        {
            get
            {
                List<Temperature> result = new List<Temperature>();
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(@"root\WMI", "SELECT * FROM MSAcpi_ThermalZoneTemperature");
                foreach (ManagementObject obj in searcher.Get())
                {
                    Double temperature = Convert.ToDouble(obj["CurrentTemperature"].ToString());
                    temperature = (temperature - 2732) / 10.0;
                    result.Add(new Temperature { CurrentValue = temperature, InstanceName = obj["InstanceName"].ToString() });
                }
                return result;
            }
        }
    }
}

9
你看了这个问题吗?楼主说他已经尝试过 MSAcpi_ThermalZoneTemperature 了... - Thomas Levesque
1
这不是CPU温度,我认为这是机箱温度。您可以使用CPUID进行检查。 - zezba9000
我不知道那段代码想要做什么,但是我得到了值-267.8。 - TizzyFoe
这个只能在Windows上运行吗?还是任何支持ASP.NET Core的主机都可以使用? - undefined

23

我相信这取决于制造商,因为它们将通过I/O端口访问。如果您有特定的主板需要使用,请查阅手册或与制造商联系。

如果您要为许多不同的主板进行操作,我建议联系SiSoftware之类的公司,或者准备阅读很多主板手册。

另外需要注意的是,并非所有主板都具有温度监测器。

您还可能遇到从内核获取特权访问的问题。


12
你可以尝试使用Open Hardware Monitor,但它不支持最新的处理器。
internal sealed class CpuTemperatureReader : IDisposable
{
    private readonly Computer _computer;

    public CpuTemperatureReader()
    {
        _computer = new Computer { CPUEnabled = true };
        _computer.Open();
    }

    public IReadOnlyDictionary<string, float> GetTemperaturesInCelsius()
    {
        var coreAndTemperature = new Dictionary<string, float>();

        foreach (var hardware in _computer.Hardware)
        {
            hardware.Update(); //use hardware.Name to get CPU model
            foreach (var sensor in hardware.Sensors)
            {
                if (sensor.SensorType == SensorType.Temperature && sensor.Value.HasValue)
                    coreAndTemperature.Add(sensor.Name, sensor.Value.Value);
            }
        }

        return coreAndTemperature;
    }

    public void Dispose()
    {
        try
        {
            _computer.Close();
        }
        catch (Exception)
        {
            //ignore closing errors
        }
    }
}

官方网站下载ZIP文件,解压并在您的项目中添加对OpenHardwareMonitorLib.dll文件的引用。


6

在页面上显示的项目网站 :) https://github.com/matteofabbri/HardwareProviders - TheQult
1
不幸的是,这个库有很多兼容性问题,例如在没有超线程的i7-9700k上,当尝试发现CPU时会抛出异常。 - Wobbles
这里有一个更新版本的OpenHardwareMonitorLib.dll: https://github.com/BrsVgl/PerformanceEfficiencySuite 这对于原始0.9.6.0版本的.dll无法显示CPU温度的Jasper Lake CPU真的很有帮助。 - sergeantKK

4

这取决于您的计算机是否支持WMI。我的计算机也无法运行此WMI演示。

但是,我通过 Open Hardware Monitor 成功获取了CPU温度。在Visual Studio中添加Openhardwaremonitor引用更加容易。请尝试以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenHardwareMonitor.Hardware;

namespace Get_CPU_Temp5
{
   class Program
   {
       public class UpdateVisitor : IVisitor
       {
           public void VisitComputer(IComputer computer)
           {
               computer.Traverse(this);
           }

           public void VisitHardware(IHardware hardware)
           {
               hardware.Update();
               foreach (IHardware subHardware in hardware.SubHardware) subHardware.Accept(this);
           }

           public void VisitSensor(ISensor sensor) { }
           public void VisitParameter(IParameter parameter) { }
       }

       static void GetSystemInfo()
       {
           UpdateVisitor updateVisitor = new UpdateVisitor();
           Computer computer = new Computer();
           computer.Open();
           computer.CPUEnabled = true;
           computer.Accept(updateVisitor);
           for (int i = 0; i < computer.Hardware.Length; i++)
           {
               if (computer.Hardware[i].HardwareType == HardwareType.CPU)
               {
                   for (int j = 0; j < computer.Hardware[i].Sensors.Length; j++)
                   {
                       if (computer.Hardware[i].Sensors[j].SensorType == SensorType.Temperature)
                               Console.WriteLine(computer.Hardware[i].Sensors[j].Name + ":" + computer.Hardware[i].Sensors[j].Value.ToString() + "\r");
                   }
               }
           }
           computer.Close();
       }

       static void Main(string[] args)
       {
           while (true)
           {
               GetSystemInfo();
           }
       }
   }
}

你需要以管理员身份运行此演示。

你可以在使用Open Hardware Monitor获取CPU温度并制作风扇冷却系统的C#教程中查看教程。


4

在最新版本的Windows 10中,提到的WMI类对我没有起作用。

在我的Dell笔记本电脑上,我可以通过PowerShell以摄氏度获取CPU温度:

$data = Get-WMIObject -Query "SELECT * FROM Win32_PerfFormattedData_Counters_ThermalZoneInformation" -Namespace "root/CIMV2"
@($data)[0].HighPrecisionTemperature

底层接口是什么?COM? .NET? 我想象它不仅仅在PowerShell中,也可能在许多其他编程语言中实现。 - Peter Mortensen

3
可以通过WMI在您的代码中完成。我发现了一个来自Microsoft的工具(WMI Code Creator v1.0),它可以为此创建代码。
WMI Code Creator工具允许您生成使用WMI完成管理任务的VBScript、C#和VB.NET代码,例如查询管理数据、从WMI类执行方法或使用WMI接收事件通知。

1
由于CPU/芯片组合越来越多,需要一个聪明的矩阵来检查所有可能的组合以识别温度数据。你真的需要一个外部的DLL,比如"LibreHardwareMonitorLib.dll"来解决这个问题。项目文件可以在这里找到。
基于此,一个PowerShell解决方案可能如下所示:
#Requires -RunAsAdministrator

cls
$dll = "LibreHardwareMonitorLib.dll"

Unblock-File -LiteralPath $dll
Add-Type -LiteralPath $dll
$monitor = [LibreHardwareMonitor.Hardware.Computer]::new()
$monitor.IsCPUEnabled = $true

$monitor.Open()
[int]$temp = foreach ($sensor in $monitor.Hardware.Sensors) {
    if ($sensor.SensorType -eq 'Temperature' -and $sensor.Name -eq 'Core Average'){
        $sensor.Value
        break
    }
}
$monitor.Close()
write-host "CPU-Package Temperature = $temp°C" -f y 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接