Search code examples
c#timerwmitemptrayicon

(C#, WMI) Tray App Displaying CPU Temp only updates value when SpeedFan App is running


I've made a simple tray app that displays the CPU Temperature and updates every second using a timer.

The tray icon displays the "CurrentTemperature" parameter retrieved from the ManagementObjectSearcher query, which is then used to create a Bitmap that displays the temperature value.

It seems to be working well, except for the fact that it always retrieves the exact same temperature value. However, if I have SpeedFan running in the background, the temperature will update accordingly.

Could anyone provide me with insight as to why the app is unable to retrieve the updated temperature value on its own?

Note: I've checked my machine's BIOS and there are no temperature readings

I'm attaching the code for anyone interested / willing to give advice

class Program
{
    private static System.Timers.Timer tmr;
    private static ContextMenu CMenu;
    private static NotifyIcon trayIcon;
    private static Color c;
    private static int Temp;
    private static int _Temp;

    private static void Main(string[] args)
    {
        tmr = new System.Timers.Timer();
        trayIcon = new NotifyIcon();
        CMenu = new ContextMenu();

        //ContextMenu
        CMenu.MenuItems.Add("Exit", Exit_Application);

        //trayIcon
        trayIcon.ContextMenu = CMenu;
        trayIcon.Visible = true;

        //Timer
        tmr.Interval = 1000;
        tmr.Elapsed += new ElapsedEventHandler(onTimerTick);
        tmr.Enabled = true;

        Temp = 0;
        Application.Run();
    }
    private static void Exit_Application(object Sender, EventArgs e) { trayIcon.Icon = null; Application.Exit(); }

    private static void onTimerTick(object Sender, ElapsedEventArgs e)
    {
        using (ManagementObjectSearcher mos = new ManagementObjectSearcher("root\\WMI", "SELECT * FROM MSAcpi_ThermalZoneTemperature"))
        {
            using (ManagementObject mo = mos.Get().OfType<ManagementObject>().First())
            {
                _Temp = int.Parse(mo["CurrentTemperature"].ToString()) / 10 - 273; //Convert To Celsius
                if (_Temp != Temp)
                {
                    Temp = _Temp;
                    trayIcon.Icon = CreateIcon(Temp);
                }
                if (Temp >= 85) { Console.Beep(); }
            }
        }  
    }
    private static Icon CreateIcon(int value)
    {
        if (value < 50) { c = Color.FromArgb(0, 255, 0); }
        else if (value >= 80){ c = Color.OrangeRed; }
        else { c = Color.Yellow; }

        using (Bitmap bm = new Bitmap(16, 16))
        {
            using (Graphics g = Graphics.FromImage(bm))
            {
                using (Brush b = new SolidBrush(c))
                {
                    g.DrawString(value.ToString(), SystemFonts.DefaultFont, b, 0, 0);
                    return Icon.FromHandle(bm.GetHicon());
                } 
            }
        }
    }
}

Solution

  • After further research it appears that WMI cannot read CPU temperatures, I found the explanation Here