Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

CPU Temperature & System Information

4.72/5 (42 votes)
7 Nov 2017CPOL5 min read 93K   10.4K  
Two classes for easy access to system information using OpenHardWareMonitor and Windows System.Management.

Introduction

Since I use a homebuilt PC, I wanted a simple application to display my CPU temperature unobstrusively on my desktop.

Background

This project started when I wanted to write a small utility to display the CPU temperature in a corner of the desktop using the open source OpenHardwareMonitorLib.dll (). Web Page here. This library provides extensive hardware information, including multiple system temperatures accessible through a Windows Management Interface (WMI). However, I found the limited documentation available somewhat confusing and had better luck using the public class enumerations provided by OHM directly, the key being to call the Update methods correctly for items and subitems before attempting to enumerate them.

Once I got it working, I created a wrapper class, OHData which has one public property, DataList and one public method, Update.

Since I was not able to extract BIOS information from OHM (even though it is visible when debugging), I also created a small separate wrapper class, WMBIOS, which gets the relevant information using System.Management (add this reference to your project as well).

Here are samples from the demo application:

The temperature window:

Image 1

The system information popup window:

Image 2

Using the Code

To use the code, include a copy of OpenHardwareMonitorLib.dll in your project, add a reference to it. Then create a local instance of OHdata, for example OHData od = new OHData(), call the update method and get the results in a List<OHMItem> object, each OHItem consisting of a Sensor Type, Sensor Name, and reading (all strings). The OHMItem class structure is a public member of OHData. OHItems in the retrieved list are preformatted for most types, such as voltages, temperatures, and fan speeds, ready to use in a ListView. To get just the CPU temperature, you can search the List for Type = "Temperature" and Name = "CPU" if you just want to use that.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using System.Management;
using OpenHardwareMonitor;
using OpenHardwareMonitor.Collections;
using OpenHardwareMonitor.Hardware;

// REQUIRES OpenHardwareMonitorLib.dll added to project

namespace <your project namespace goes here>
{
    static class Program
    {
        /// 
        /// The main entry point for the application.
        /// 
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
            }
    
    /// Wrapper For OpenHarwareMonitor.dll
    /// 
    public class OHData
    {
        // DATA ACCESSOR
        public List<ohmitem> DataList
        {
            get
            {
                return ReportItems;
            }
            set
            {

            }

        }
        // UPDATE METHOD
        public void Update()
        {
            UpdateOHM();
        }

        // for report compilation
        public class OHMitem
        {
            public OHMitem()
            {
            }
            public string name
            {
                get
                {
                    return Name;
                }
                set
                {
                    Name = value;
                }
            }
            public string type
            {
                get
                {
                    return OHMType;
                }
                set
                {
                    OHMType = value;
                }
            }
            public string reading
            {
                get
                {
                    return OHMValue;
                }
                set
                {
                    OHMValue = value;
                }
            }

            private string Name = String.Empty;
            private string OHMType = String.Empty;
            private string OHMValue = String.Empty;

        }
        // for report compilation
        private List<ohmitem> ReportItems = new List<ohmitem>();
        // ADDS ITEMS TO REPORT
        private void AddReportItem(string ARIName, string ARIType, string ARIValue)
        {
            // int readingwidth = 26;
            if (ARIType == "Data")
            {
                return; // ignore data items
            }
            OHMitem ARItem = new OHMitem();
            ARItem.name = ARIName;
            ARItem.type = ARIType + ": ";
            ARItem.reading = ARIValue;
            if (ARIType == "GpuAti")
            {
                ARItem.type = "Graphics Card";
            }

            if (ARIType == "Temperature")
            {
                try
                {
                    double temp = Convert.ToDouble(ARIValue);
                    ARItem.reading = ((((9.0 / 5.0) * temp) + 32).ToString("000.0") + " F");
                }
                catch
                {
                    
                    return;
                }
            }
            if (ARIType == "Clock")
            {
                try
                {
                    double temp = Convert.ToDouble(ARIValue);
                    if (temp < 1000)
                    {
                        ARItem.reading = (temp.ToString("F1") + " MHZ");
                    }
                    else
                    {
                        temp = temp / 1000;
                        ARItem.reading = (temp.ToString("F1") + " GHZ");
                    }
                }
                catch
                {
                    return;
                }

            }
            if (ARIType == "Control" || ARIType == "Load")
            {
                try
                {
                    double temp = Convert.ToDouble(ARIValue);
                    ARItem.name = ARIName;
                    ARItem.reading = (temp.ToString("F0") + " %");
                }
                catch
                {
                    return;
                }
            }
            if (ARIType == "Voltage")
            {
                try
                {
                    double temp = Convert.ToDouble(ARIValue);
                    ARItem.name = ARIName;
                    ARItem.reading = (temp.ToString("F1") + " V");
                }
                catch
                {
                    return;
                }
            }
            // 07-28-2016 Added This item
            if (ARIType == "Fan")
            {
                try
                {
                    double rpm = Convert.ToDouble(ARIValue);
                    ARItem.name = ARIName;
                    ARItem.reading = (rpm.ToString("F0") + " RPM");
                }
                catch
                {
                    return;
                }
            }

            ReportItems.Add(ARItem);
        }
        // LOCAL INSTANCE OHM
        private OpenHardwareMonitor.Hardware.Computer computerHardware = 
        new OpenHardwareMonitor.Hardware.Computer();
        // UPDATE OHM DATA
        private void UpdateOHM()
        {
            
            string s = String.Empty;
            string name = string.Empty;
            string type = string.Empty;
            string value = string.Empty;
            int x, y, z, n;
            int hardwareCount;
            int subcount;
            int sensorcount;
            ReportItems.Clear();
            computerHardware.MainboardEnabled = true;
            computerHardware.FanControllerEnabled = true;
            computerHardware.CPUEnabled = true;
            computerHardware.GPUEnabled = true;
            computerHardware.RAMEnabled = true;
            computerHardware.HDDEnabled = true;
            computerHardware.Open();
            hardwareCount = computerHardware.Hardware.Count();
            for (x = 0; x < hardwareCount; x++)
            {
                name = computerHardware.Hardware[x].Name;
                type = computerHardware.Hardware[x].HardwareType.ToString();
                value = ""; // no value for non-sensors;
                AddReportItem(name, type, value);

                subcount = computerHardware.Hardware[x].SubHardware.Count();

                // ADDED 07-28-2016
                // NEED Update to view Subhardware
                for (y = 0; y < subcount; y++)
                {
                    computerHardware.Hardware[x].SubHardware[y].Update();
                }
                //
               
                if (subcount > 0)
                {
                    for (y = 0; y < subcount; y++)
                    {
                        sensorcount = computerHardware.Hardware[x].
                        SubHardware[y].Sensors.Count();
                        name = computerHardware.Hardware[x].SubHardware[y].Name;
                        type = computerHardware.Hardware[x].SubHardware[y].
                        HardwareType.ToString();
                        value = "";
                        AddReportItem(name, type, value);

                        if (sensorcount > 0)
                        {
                            
                            for (z = 0; z < sensorcount; z++)
                            {
                                
                                name = computerHardware.Hardware[x].
                                SubHardware[y].Sensors[z].Name;
                                type = computerHardware.Hardware[x].
                                SubHardware[y].Sensors[z].SensorType.ToString();
                                value = computerHardware.Hardware[x].
                                SubHardware[y].Sensors[z].Value.ToString();
                                AddReportItem(name, type, value);
                                
                            }
                        }
                    }
                }
                sensorcount = computerHardware.Hardware[x].Sensors.Count();
                
                if (sensorcount > 0)
                {
                    for (z = 0; z < sensorcount; z++)
                    {
                        name = computerHardware.Hardware[x].Sensors[z].Name;
                        type = computerHardware.Hardware[x].Sensors[z].SensorType.ToString();
                        value = computerHardware.Hardware[x].Sensors[z].Value.ToString();
                        AddReportItem(name, type, value);
                        
                    }
                }
            }
           computerHardware.Close();
        }
    }
    /// <summary>
    /// Wrapper for BIOS Information from Win_32BIOS WMI
    /// </summary>
    public class WMIBIOS
    {
        public string Name
        {
            get
            {
                return name;
            }
           
        }
        public string Manufacturer
        {
            get
            {
                return manufacturer;
            }
        }
        public string Date
        {
            get
            {
                return FormatDate(date);
            }

        }
        public string Version
        {
            get
            {
                return version;
            }

        }
        public void Update()
        {
            update();
        }
        private string name = String.Empty;
        private string manufacturer = String.Empty;
        private string date = String.Empty;
        private string version = String.Empty;
        // Get BIOS Data using WMI
        private void update()
        {
            
            
            ManagementObjectSearcher searcher = 
            new ManagementObjectSearcher(@"\\.\root\cimv2", "SELECT * FROM Win32_BIOS");
            ManagementObjectCollection collection = searcher.Get();
            foreach (ManagementObject o in collection)
            {
                try
                {
                    name = Convert.ToString(o.GetPropertyValue("Name"));
                }
                catch
                {
                    name = String.Empty;
                }
                try
                {
                    date = Convert.ToString(o.GetPropertyValue("ReleaseDate"));
                }
                catch
                {
                    date = String.Empty;
                }
                try
                {
                    manufacturer = Convert.ToString(o.GetPropertyValue("Manufacturer"));
                }
                catch
                {
                    manufacturer = String.Empty;
                }
                try
                {
                    version = Convert.ToString(o.GetPropertyValue("SMBIOSBIOSVersion"));
                }
                catch
                {
                    version = String.Empty;
                }
            }
            searcher.Dispose();
            return;
        }
        // FORMAT DATE FROM WIN_32 BIOS INTO USABLE FORM
        private string FormatDate(string rawdata)
        {
            string result = String.Empty;
            string year = String.Empty;
            string month = String.Empty;
            string day = String.Empty;
            try
            {
                year = rawdata.Substring(0, 4);
                month = rawdata.Substring(4, 2);
                day = rawdata.Substring(6, 2);
            }
            catch
            {
                return result;
            }
            result = month + "-" + day + "-" + year;
            return result;
        }
    }
}

Points of Interest

Between these two classes, most useful system information is available. Note that OHM returns different sensors and results depending on the underlying hadware. For example, system board voltages that show up on my home built gigabyte motherboard PC don't show up in the list on my Lenovo Carbon X1.

The "Temperature.exe" sample application shows how to use them. It opens a small partially transparent window in the right lower corner of the screen with the CPU temperature display, updating every 60 seconds. Right-clicking the window opens a context menu with options to quit, display system information, and changes the update interval. Note that I had to add a custom manifest to the project for Windows 8 and 10 with a higher access privilege, probably because OpenHardwareMonitor interacts with the hardware directly. This wasn't necessary in Windows 7. This shows up as "app.manifest" in Solution Explorer. A custom manifest can be added in the Application Window of Project->Properties. With Version 1.0.2.3, I added a backup method for calculating available Free and Used Memory if this is missing from the OHMonitor data, and more information from other sources regarding the BIOS. There are still some OHMonitor subitems where the expected data remains blank. If someone finds a solution to extracting the missing fields, please let me know. Using Visual Studio 2015 to run the demo app in debug mode, it's clear that more data is actually available in the OHMonitor class than is coming through when the program runs, so the method for reading the enumerated values could be improved. I have been able to find only limited online documentation for the OHM library so far.

That said, I have found the library to return most relevant information from my homebuilt generic hardware PC which uses a Gigabyte GA-Z170X-UD5 motherboard and Windows 10-64 as well as my older Lenovo Carbon X1 laptop which runs Windows 10-32. Most importantly for a home builder, the CPU temperature is accurate when checked against other sources, such as the CorsairLink utility that came with my liquid CPU cooler.

Update 11-07-2017  Following a posted suggestion, I tried leaving the OHM ComputerHardware instance open after reading its values, rather than using the .Close() method after each use.  This seems to miss some subitems in the hardware enumeration, so you must Open and Close the instance each time you query it.  I have not had further success in using the WMI interface provided by OHM, for which there is little if any documentation.  The sample application now averages the reported CPU temperatures to get the temp it displays.  Overall, the information it reports is now very close to OHM's own application and to data from the BIOS or third party system information utilities such as CorsairLink.  Additional outside items I added to the list with this version are the current display resolution and the Windows 10 Build number.

Update 11-24-2019 Following a suggestion by Member 14615649, Added an Options feature and temperature logging. Yellow and Red alert temperature thresholds can be customized as can the transparency of the small display window. The program will also save CPU temperatures to a log and display them in graph form using the net DataVisualization API.  To zoom portions of the chart, click and drag to select an area of interest on it. Hovering over a datapoint on the graph shows its actual temperature reading.

History

  • 07-30-2016 1st posting ver 1.0.0.9
  • 06-07-2017 2nd posting ver 1.0.2.3
  • 08-07-2017 3rd posting ver 1.0.2.4
  • 11-07-2017 4th posting ver 1.0.2.8
  • 11-24-2019 5th posting ver 1.0.4.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)