Click here to Skip to main content
15,867,594 members
Articles / Web Development / HTML

CPU Temperature & System Information

Rate me:
Please Sign up or sign in to vote.
4.72/5 (42 votes)
7 Nov 2017CPOL5 min read 88.5K   10.2K   81   35
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)


Written By
United States United States
I am a retired MD who enjoys programming.

Comments and Discussions

 
QuestionSystem.NullReferenceException when starting app from SOURCE.zip Pin
A.J.G. Beentjes17-Mar-22 9:49
A.J.G. Beentjes17-Mar-22 9:49 
AnswerRe: System.NullReferenceException when starting app from SOURCE.zip Pin
Howard 944849023-Mar-22 14:32
Howard 944849023-Mar-22 14:32 
AnswerRe: System.NullReferenceException when starting app from SOURCE.zip Pin
A.J.G. Beentjes24-Mar-22 5:05
A.J.G. Beentjes24-Mar-22 5:05 
GeneralRe: System.NullReferenceException when starting app from SOURCE.zip Pin
Howard 944849024-Mar-22 5:47
Howard 944849024-Mar-22 5:47 
AnswerRe: System.NullReferenceException when starting app from SOURCE.zip Pin
A.J.G. Beentjes25-Mar-22 6:42
A.J.G. Beentjes25-Mar-22 6:42 
GeneralRe: System.NullReferenceException when starting app from SOURCE.zip Pin
Howard 94484903-Apr-22 6:42
Howard 94484903-Apr-22 6:42 
AnswerRe: System.NullReferenceException when starting app from SOURCE.zip Pin
A.J.G. Beentjes4-Apr-22 0:49
A.J.G. Beentjes4-Apr-22 0:49 
SuggestionAlways on top option? Pin
Member 146156497-Oct-19 23:35
Member 146156497-Oct-19 23:35 
GeneralRe: Always on top option? Pin
Member 1461564910-Oct-19 22:51
Member 1461564910-Oct-19 22:51 
GeneralRe: Always on top option? Pin
Howard 94484905-Nov-19 6:31
Howard 94484905-Nov-19 6:31 
QuestionCan this code can be used with .NET Core 2.2? Pin
Member 1203040427-Mar-19 12:45
Member 1203040427-Mar-19 12:45 
AnswerRe: Can this code can be used with .NET Core 2.2? Pin
Howard 944849026-Apr-19 12:44
Howard 944849026-Apr-19 12:44 
QuestionBoth DEMO and SOURCE zip files corrupt (as at 29 Jan 2019)? Pin
Tony Austin28-Jan-19 2:46
Tony Austin28-Jan-19 2:46 
AnswerRe: Both DEMO and SOURCE zip files corrupt (as at 29 Jan 2019)? Pin
Howard 944849026-Apr-19 12:38
Howard 944849026-Apr-19 12:38 
QuestionTimely Tool Pin
Roger Wright14-Nov-17 6:43
professionalRoger Wright14-Nov-17 6:43 
AnswerRe: Timely Tool Pin
Howard 944849016-Nov-17 5:30
Howard 944849016-Nov-17 5:30 
Questionsuggestion Pin
dan o1-Oct-17 21:07
dan o1-Oct-17 21:07 
AnswerRe: suggestion Pin
Howard 944849013-Oct-17 6:19
Howard 944849013-Oct-17 6:19 
AnswerRe: suggestion Pin
Howard 94484907-Nov-17 11:53
Howard 94484907-Nov-17 11:53 
GeneralMy vote of 1 Pin
Jordan Wilde31-Aug-17 7:42
Jordan Wilde31-Aug-17 7:42 
GeneralRe: My vote of 1 Pin
Howard 94484904-Sep-17 11:46
Howard 94484904-Sep-17 11:46 
GeneralMy vote of 2 Pin
tbayart25-Jul-17 21:03
professionaltbayart25-Jul-17 21:03 
GeneralRe: My vote of 2 Pin
Howard 94484907-Aug-17 10:03
Howard 94484907-Aug-17 10:03 
GeneralMy vote of 5 Pin
Аslam Iqbal9-Jun-17 22:52
professionalАslam Iqbal9-Jun-17 22:52 
GeneralRe: My vote of 5 Pin
Howard 944849013-Jun-17 6:14
Howard 944849013-Jun-17 6:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.