Click here to Skip to main content
13,629,406 members
Click here to Skip to main content
Add your own
alternative version

Stats

3K views
247 downloads
19 bookmarked
Posted 10 Jul 2018
Licenced CPOL

Computer Temperatures, Fan Speeds, etc.

, 10 Jul 2018
Rate this:
Please Sign up or sign in to vote.
Fully exploit features of OpenHardwareMonitorLib.dll

Introduction

I have a homebuilt desktop with an ASUS P6T motherboard. It's about 7-8 years old, but still quite powerful and functions beautifully. ASUS originally provided PC Probe II to monitor temperatures and fan speeds, but stopped supporting it for the P6T when Windows 10 came out. And since then, I've been operating without a satisfactory sensor app. Unfortunately, the 3rd party sensor apps available are a bit quirky, or non-intuitive, or can't be configured the way I'd like. Then again, perhaps I'm just overly picky.

Some years ago, I considered OpenHardwardMonitor, an open source DLL that seems to cover everything needed. Unfortunately, the documentation they provide is minimal at best, and as of this writing, clearly out of date. And then Howard wrote a great article here on CodeProject that provided enough information to get me going. Unfortunately, he was unable to fully exploit OpenHardwareMonitor's capabilities. But after some experimentation, I think I've managed to do so.

Using the Code

The code is implemented as a Visual Studio 2015 self-contained project. It includes OpenHardwareMonitorLib.dll version 0.8.0 Beta. You should be able to download the code file, unzip it, load it into VS, and compile and execute it.

Implementation

The key to the implementation is a public wrapper class I created named ohmDataTree. It implements:

  • the IDisposable interface to ensure that OHM's resources are properly shut down regardless
  • properties MainboardEnabled, FanControllerEnabled, CPUEnabled, GPUEnabled, RAMEnabled and HDDEnabled to expose OHM's comparable native properties, which allow the user to disable unneeded aspects of OHM; I assume that speeds up the sensor scan, but I haven't done any tests to confirm that
  • variable hWareList, which gives access to the hardware and sensor information in the form of a linked-list binary tree of ohmHwNode classes—more on that later
  • method Update, which creates hWareList, a linked list of hardware nodes
  • variable configChanged, which indicates that the hardware configuration has changed since the last call to Update; strictly for external information purposes; it's up to the user to act upon this information, and reset configChanged if needed

Note that configChanged is set by monitoring OHM's HardwareAdded and HardwareRemoved events. Through testing, I determined that these events are fired when one of the xxxEnabled properties is set or reset. I also experimented by plugging in and removing old (6-8 years) and new (<6 months) USB hard drives and USB stick drives. In all cases, neither of the events fired, and the added drives did not immediately show up in the scan. They only showed up if I shut the application down and restarted it. They did show up immediately if I called the Open() and Close() methods in the OpenHardwareMonitor.Hardware.Computer class on each update. But both methods appear to be CPU intensive, and frequently calling them that way bogged down my system, literally made it unusable.

I posted an issue on GitHub to notify the OHM developers. Dan Neel responded immediately and kudos to him for his quick reply. He recommended I catch the USB-connected event. I set up a WMI ManagementEventWatcher class and that worked, notifying me when a USB device was inserted. In response, I executed the Close() and Open() events to update OHM. Doing so in response to the event meant I didn't execute those methods on every timer tick and bog the system down. Unfortunately, it appears that OHM opens a handle to each device and keeps it open, or something like that. Windows would not allow me to eject the device until I stopped monitoring it with OHM. Because of that, I disabled that portion of the code by placing it in a #define TrapUSB. If you want to experiment with it, just define TrapUSB.

The information for each hardware node is stored in a class named ohmHwNode. Each hardware node can contain a list of child hardware nodes, and there appears to be no limit on the depth of child nodes—each child node can contain a further list of child nodes. Hence, I implemented the sensor scan with a recursive call to the method ScanHardware. It accepts an OHM IHardware array of hardware nodes, and a pointer to the ohmHwNode parent, which is null in the case of the nodes in the uppermost IHardware array. The ohmHwNode class is structured as follows:

public class ohmHwNode
{
    public ohmHwNode ohmParent = null;     //pointer to the parent node
    public ohmHwNode[] ohmChildren = null; //array of pointers to the child nodes

    public string name = "";               //Hardware name
    public OpenHardwareMonitor.Hardware.HardwareType type; //Hardware type
    public OpenHardwareMonitor.Hardware.Identifier id;

    public ohmSensor[] sensors = null;     //array of ohmSensors in this hardware node
}

The ohmParent and ohmChildren pointers are the links that connect the linked-list binary tree. They allow me to walk the tree in the method AddItems in the file ProbeForm.cs to retrieve the sensor data.

Each hardware node contains an OHM ISensor array of data for its sensors, which can be empty for any given hardware node. I store the data for each sensor in a container class named ohmSensor which is structured as follows:

public class ohmSensor
{
    public string Name = "";                             //Sensor Name
    public string Identifier = "";                       //Sensor Identifier
    public OpenHardwareMonitor.Hardware.SensorType Type; //Sensor Type
    public float? Value;                                 //nullable native Sensor Value
    public float? Min;                                   //nullable native Sensor Min
    public float? Max;                                   //nullable native Sensor Max
    public string stValue = "";                          //formatted Value String
    public string stMin = "";                            //formatted Min String
    public string stMax = "";                            //formatted Max String
    public int Index = 0;
}

The stValue, stMin and stMax strings are formatted from the returned nullable values by the ohmDataTree method getValueString, which is implemented as follows:

private string getValueString(OpenHardwareMonitor.Hardware.SensorType type, float? value)
{
    if (value == null)
        return "null";
    switch (type)
    {
        case OpenHardwareMonitor.Hardware.SensorType.Voltage:
            return value.Value.ToString("N3") + " v";
        case OpenHardwareMonitor.Hardware.SensorType.Clock:
            return value.Value.ToString("N0") + " MHz";
        case OpenHardwareMonitor.Hardware.SensorType.Temperature:
            return value.Value.ToString("N1") + " °C";
        case OpenHardwareMonitor.Hardware.SensorType.Level:
        case OpenHardwareMonitor.Hardware.SensorType.Control:
        case OpenHardwareMonitor.Hardware.SensorType.Load:
            return value.Value.ToString("N1") + " %";
        case OpenHardwareMonitor.Hardware.SensorType.Fan:
            return value.Value.ToString("N0") + " rpm";
        case OpenHardwareMonitor.Hardware.SensorType.Flow:
            return value.Value.ToString("N1") + " L/h";

        //No documentation so had to guess on these:
        case OpenHardwareMonitor.Hardware.SensorType.SmallData:
            return value.Value.ToString("N1") + " MB";
        case OpenHardwareMonitor.Hardware.SensorType.Data:
            return value.Value.ToString("N1") + " GB";
        case OpenHardwareMonitor.Hardware.SensorType.Power:
            return value.Value.ToString("N1") + " W";

        //No documentation and no guess on these:
        //case OpenHardwareMonitor.Hardware.SensorType.Factor:
    }
    return value.ToString();
}

Note that, as of this writing, the OHM documentation lists the sensor type enumeration as:

public enum SensorType
{
    Voltage,
    Clock,
    Temperature,
    Load,
    Fan,
    Flow,
    Control,
    Level
}

But in the present version (0.8.0 Beta) of OHM, SmallData, Data, Factor and Power have been added. OHM's outdated and insufficient documentation is its biggest problem, and probably the biggest hurdle to widespread implementation.

Run as Administrator

It is critically important to run the application with Administrator privileges. When I run the application without Administrator privileges on my desktop, I get the following:

Note the sensors with a value of null.

On the other hand, when I run it with Administrator privileges, I get this:

Note that the "No Sensors" entry under the motherboard only means that the motherboard hardware node has no sensors. However, it does have a child hardware node that contains all the motherboard sensors.

If you run Visual Studio with Administrator privileges, it will automatically run both debug and release versions with Administrator privileges. If you run Visual Studio with normal privileges, the Probe program will prompt you to elevate privileges. If you want to see how your system responds without, answer No to the prompt.

Things To Do

  1. Implement SensorAdded and SensorRemoved event handlers in the ohmHwNode class.
  2. I am concerned that on each timer tick (once every second), I destroy and recreate 6-7 ohmHwNode classes and 40-50 ohmSensor classes. But I've monitored the situation with Task Manager's Performance tools, and Visual Studio seems to be disposing of the deallocated memory in a timely fashion.
  3. Create a nice, configurable, minimalist, floating desktop app to monitor fan speeds and temperatures, with alarms.
  4. Try to understand many of the undocumented features of OHM.

History

  • 2018.07.10: First implementation and publication

License

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

Share

About the Author

JamesDoty
Engineer self-employed
United States United States
Jim is a scientist with a Ph.D. in Electrical Engineering. His specialty is laser physics. He's been writing code for over 50 years.

Jim is also a published author of Science Fiction and Fantasy. His first success came through self-publishing when one of his novels went viral and became an Amazon best-seller. That led to traditional contracts with publishers like Open Road Media and Harper Collins. He now has ten published novels, with three more in the works.

You may also be interested in...

Comments and Discussions

 
QuestionRun As Admin Pin
Member 1115584313-Jul-18 12:11
memberMember 1115584313-Jul-18 12:11 
Questionworks fine Pin
avisal12-Jul-18 8:56
professionalavisal12-Jul-18 8:56 

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.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01-2016 | 2.8.180712.1 | Last Updated 10 Jul 2018
Article Copyright 2018 by JamesDoty
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid