1

I'm using this code to get cpu temperature, but I'm getting 'not supported' instead of the temperature.

public static string getCpuTemperature()
{
    try
    {

        ManagementObjectSearcher searcher =
            new ManagementObjectSearcher("root\\WMI",
            "SELECT * FROM MSAcpi_ThermalZoneTemperature");
        //Win32_TemperatureProbe

        foreach (ManagementObject queryObj in searcher.Get())
        {
            double temp = Convert.ToDouble(queryObj["CurrentTemperature"].ToString());
            double temp_critical = Convert.ToDouble(queryObj["CriticalTripPoint"].ToString());
            double temp_cel = (temp / 10 - 273.15);
            double temp_critical_cel = temp_critical / 10 - 273.15;
            return temp_cel.ToString() + " _ " + temp_critical_cel.ToString();
        }
    }
    catch (ManagementException e)
    {
        //MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
        return e.Message.ToString();
    }
    return "";
}

I've googled the problem and have seen many answers for this including, - the motherboard doesn't support this feature - run VS with administration right etc...

but none of them are true, because programs like OpenHardwareMonitor and SpeedFan show the temperature of cpu and gpu, Hdd temperature, cpu fan speed, and all other informations.

I want to know how do they do that? how is that I get 'not supported' message and these programs don't.

jgauffin
  • 99,844
  • 45
  • 235
  • 372
Lithium
  • 589
  • 2
  • 11
  • 24
  • 1
    ehh, from each core? All cores are in the same CPU and do typically have the same temperature. (Unless you have a multi CPU system ) – jgauffin Jun 19 '14 at 08:09
  • 2
    That is wildly incorrect, most software runs on a single core so you'll get a large temperature difference. – NibblyPig Jun 19 '14 at 08:14
  • I suspect the software products you refer to are not using WMI. – Jodrell Jun 19 '14 at 08:15
  • the program 'OpenHardwareMonitor' show temperature of each core separately, so does 'SpeedFan'. this is not that important for me. I just want to get a number showing my cpu temperature. – Lithium Jun 19 '14 at 08:20
  • @Jodrell : then how to they do that? any idea? – Lithium Jun 19 '14 at 08:21
  • 2
    As the name suggests OpenHardwareMonitor is open source, you can look at the code here https://code.google.com/p/open-hardware-monitor/source/browse/trunk/Hardware/CPU/IntelCPU.cs for instance. – Jodrell Jun 19 '14 at 08:26
  • wow! that's lots of codes. I should check it out. seems it's the only way. all answers lead me to this software :) – Lithium Jun 19 '14 at 08:38
  • 2
    @Lithium Why not just reference `OpenHardwareMonitorLib.dll` in your application? – Rotem Jun 19 '14 at 09:11
  • @Rotem thanks, I didn't know I can do that ;-) worked like a charm! you saved me lots of time – Lithium Jun 19 '14 at 09:35

3 Answers3

3

This is not a complete answer but hopefully it helps.

After perusing the code at https://code.google.com/p/open-hardware-monitor/source/browse/trunk/, I can't fully understand this code without downloading it all and investigating further.

The magic seems to happen here,

public override void Update() {
  base.Update();

  for (int i = 0; i < coreTemperatures.Length; i++) {
    uint eax, edx;
    // if reading is valid
    if (Ring0.RdmsrTx(IA32_THERM_STATUS_MSR, out eax, out edx,
        1UL << cpuid[i][0].Thread) && (eax & 0x80000000) != 0) 
    {
      // get the dist from tjMax from bits 22:16
      float deltaT = ((eax & 0x007F0000) >> 16);
      float tjMax = coreTemperatures[i].Parameters[0].Value;
      float tSlope = coreTemperatures[i].Parameters[1].Value;
      coreTemperatures[i].Value = tjMax - tSlope * deltaT;
    } else {
      coreTemperatures[i].Value = null;
    }
  }

  ...

This code extracts the temperature data from the result of Ring0.RdmsrTx.

Ring0 is a C implementation, the code of which is in the repository here. This reads the Model Specific Register data from the CPU driver.

There is more detail in this question.

Jodrell
  • 34,946
  • 5
  • 87
  • 124
  • 1
    The documentation also says that there is a WMI provider already available. http://openhardwaremonitor.org/documentation/ – NoviceProgrammer Jun 19 '14 at 09:23
  • @NoviceProgrammer that could be a pragmatic solution that would make it simple to benefit from future updates to OpenHardwareMonitor. – Jodrell Jun 19 '14 at 09:27
  • thanks for the reply, but I'm using its dll (openHardwareMonitorLib.dll) it does my job. – Lithium Jun 19 '14 at 09:37
  • @Lithium, that's probably what I'd do but, Its not what you asked of course. – Jodrell Jun 19 '14 at 09:47
  • @Jordell Yes I was looking for an example which is doing this job, but all links and guides lead me to openHardwareMonitor. it takes a lot of time from me to do this, and at the end I should copy codes from openHardwareMonitor finally. so why don't I use its dll. I just didn't know that I could use this dll in my project. that was all – Lithium Jun 19 '14 at 10:42
  • 1
    A ring buffer? Before looking at the source code, Ring0 in this context to me would be interpreted as ring 0 code, which is obviously required to read the msr – Lewis Kelsey May 28 '20 at 21:09
  • 1
    [Ring0](https://en.wikipedia.org/wiki/Protection_ring) relates to the Kernel in the x86 protection architecture. *"On most operating systems, Ring 0 is the level with the most privileges and interacts most directly with the physical hardware such as certain CPU functionality (e.g. the control registers) and I/O controllers."* – not2qubit Jun 23 '23 at 15:44
1

Easiest way would be probably to find a tool that can output the information you need in machine-readable way and then process that output. SpeedFan logs temperature to logs, you could just read the latest reading from the logs.

I realize this might not be an ideal solution, but it is the only universal. Querying CPU temperature in a Windows system is not an easy task.

data
  • 2,563
  • 1
  • 21
  • 25
  • 1
    That is side stepping the question. Is too hard etc. etc. etc. – Jodrell Jun 19 '14 at 08:31
  • 2
    I did not say "too hard". Everything can be done if sufficient time and resources are available. The truth is that it is best to use a tried and tested solution to ouput the CPU temp. Not re-invent the wheel, so to say. Of course it all depends on the needs of the OP, but they did not specify how sophisticated the solution should be. This is a **quick and dirty** solution - I do not deny it. – data Jun 19 '14 at 08:34
  • the application I'm developing is going to work on big server computers to monitor their performance, and show information about these servers to the owner of them. so it is important to do the job right from the program, not reading other software's logs. I know it's not going to be easy :) so any idea any lead would be appreciated! – Lithium Jun 19 '14 at 08:34
0

I'm probably very late to answer this, but just in case someone stumbles upon this in the future, here's the way I did it:

public string getCPUTemp()
        {
            UpdateVisitor updateVisitor = new UpdateVisitor();
            Computer computer = new Computer();
            computer.Open();
            computer.CPUEnabled = true;
            computer.Accept(updateVisitor);
            string res = "";
            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) res = String.Concat(res, (computer.Hardware[i].Sensors[j].Name + ": " + computer.Hardware[i].Sensors[j].Value.ToString() + "ºC" + "\r"));
                        if (computer.Hardware[i].Sensors[j].Value.ToString() == "") { res = ""; return res; }
                    }

                }
            }

It worked perfectly with me (even though it didn't work for the GPU part). You just have to download OpenHardwareMonitor (https://openhardwaremonitor.org/), then add the reference to the OpenHardwareMonitorLib.dll which is in the \openhardwaremonitor\Bin\Debug folder, then add "using OpenHardwareMonitor.Hardware;" at the top.

Hope it can still help someone even if not OP!

S. M.
  • 227
  • 1
  • 12