I posted this question, asking how to get the CPU and GPU temp on Windows 10: Get CPU and GPU Temp using Python Windows. For that question, I didn't include the restriction (at least when I first posted the answer, and for quite a bit after that) for no admin access. I then modified my question to invalidate answers that need admin access (which the only working answer then). A mod rolled back to a previous version of my question, and asked me to post a new question, so I have done that.
I was wondering if there was a way to get the CPU and the GPU temperature in python. I have already found a way for Linux (using psutil.sensors_temperature
), and I wanted to find a way for Windows.
Info:
OS: Windows 10
Python: Python 3.8.3 64-bit (So no 32 bit DLLs)
Below are some of the stuff I tried:
When I try doing the below, I get None (from here - https://stackoverflow.com/a/3264262/13710015):
import wmi
w = wmi.WMI()
prin(w.Win32_TemperatureProbe()[0].CurrentReading)
When I try doing the below, I get an error (from here - https://stackoverflow.com/a/3264262/13710015):
import wmi
w = wmi.WMI(namespace="root\wmi")
temperature_info = w.MSAcpi_ThermalZoneTemperature()[0]
print(temperature_info.CurrentTemperature)
Error:
wmi.x_wmi: <x_wmi: Unexpected COM Error (-2147217396, 'OLE error 0x8004100c', None, None)>
When I tried doing the below, I got (from here - https://stackoverflow.com/a/58924992/13710015):
import ctypes
import ctypes.wintypes as wintypes
from ctypes import windll
LPDWORD = ctypes.POINTER(wintypes.DWORD)
LPOVERLAPPED = wintypes.LPVOID
LPSECURITY_ATTRIBUTES = wintypes.LPVOID
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
GENERIC_EXECUTE = 0x20000000
GENERIC_ALL = 0x10000000
FILE_SHARE_WRITE=0x00000004
ZERO=0x00000000
CREATE_NEW = 1
CREATE_ALWAYS = 2
OPEN_EXISTING = 3
OPEN_ALWAYS = 4
TRUNCATE_EXISTING = 5
FILE_ATTRIBUTE_NORMAL = 0x00000080
INVALID_HANDLE_VALUE = -1
FILE_DEVICE_UNKNOWN=0x00000022
METHOD_BUFFERED=0
FUNC=0x900
FILE_WRITE_ACCESS=0x002
NULL = 0
FALSE = wintypes.BOOL(0)
TRUE = wintypes.BOOL(1)
def CTL_CODE(DeviceType, Function, Method, Access): return (DeviceType << 16) | (Access << 14) | (Function <<2) | Method
def _CreateFile(filename, access, mode, creation, flags):
"""See: CreateFile function http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).asp """
CreateFile_Fn = windll.kernel32.CreateFileW
CreateFile_Fn.argtypes = [
wintypes.LPWSTR, # _In_ LPCTSTR lpFileName
wintypes.DWORD, # _In_ DWORD dwDesiredAccess
wintypes.DWORD, # _In_ DWORD dwShareMode
LPSECURITY_ATTRIBUTES, # _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes
wintypes.DWORD, # _In_ DWORD dwCreationDisposition
wintypes.DWORD, # _In_ DWORD dwFlagsAndAttributes
wintypes.HANDLE] # _In_opt_ HANDLE hTemplateFile
CreateFile_Fn.restype = wintypes.HANDLE
return wintypes.HANDLE(CreateFile_Fn(filename,
access,
mode,
NULL,
creation,
flags,
NULL))
handle=_CreateFile('\\\\\.\PhysicalDrive0',GENERIC_WRITE,FILE_SHARE_WRITE,OPEN_EXISTING,ZERO)
def _DeviceIoControl(devhandle, ioctl, inbuf, inbufsiz, outbuf, outbufsiz):
"""See: DeviceIoControl function
http://msdn.microsoft.com/en-us/library/aa363216(v=vs.85).aspx
"""
DeviceIoControl_Fn = windll.kernel32.DeviceIoControl
DeviceIoControl_Fn.argtypes = [
wintypes.HANDLE, # _In_ HANDLE hDevice
wintypes.DWORD, # _In_ DWORD dwIoControlCode
wintypes.LPVOID, # _In_opt_ LPVOID lpInBuffer
wintypes.DWORD, # _In_ DWORD nInBufferSize
wintypes.LPVOID, # _Out_opt_ LPVOID lpOutBuffer
wintypes.DWORD, # _In_ DWORD nOutBufferSize
LPDWORD, # _Out_opt_ LPDWORD lpBytesReturned
LPOVERLAPPED] # _Inout_opt_ LPOVERLAPPED lpOverlapped
DeviceIoControl_Fn.restype = wintypes.BOOL
# allocate a DWORD, and take its reference
dwBytesReturned = wintypes.DWORD(0)
lpBytesReturned = ctypes.byref(dwBytesReturned)
status = DeviceIoControl_Fn(devhandle,
ioctl,
inbuf,
inbufsiz,
outbuf,
outbufsiz,
lpBytesReturned,
NULL)
return status, dwBytesReturned
class OUTPUT_temp(ctypes.Structure):
"""See: http://msdn.microsoft.com/en-us/library/aa363972(v=vs.85).aspx"""
_fields_ = [
('Board Temp', wintypes.DWORD),
('CPU Temp', wintypes.DWORD),
('Board Temp2', wintypes.DWORD),
('temp4', wintypes.DWORD),
('temp5', wintypes.DWORD)
]
class OUTPUT_volt(ctypes.Structure):
"""See: http://msdn.microsoft.com/en-us/library/aa363972(v=vs.85).aspx"""
_fields_ = [
('VCore', wintypes.DWORD),
('V(in2)', wintypes.DWORD),
('3.3V', wintypes.DWORD),
('5.0V', wintypes.DWORD),
('temp5', wintypes.DWORD)
]
def get_temperature():
FUNC=0x900
outDict={}
ioclt=CTL_CODE(FILE_DEVICE_UNKNOWN, FUNC, METHOD_BUFFERED, FILE_WRITE_ACCESS)
handle=_CreateFile('\\\\\.\PhysicalDrive0',GENERIC_WRITE,FILE_SHARE_WRITE,OPEN_EXISTING,ZERO)
win_list = OUTPUT_temp()
p_win_list = ctypes.pointer(win_list)
SIZE=ctypes.sizeof(OUTPUT_temp)
status, output = _DeviceIoControl(handle, ioclt , NULL, ZERO, p_win_list, SIZE)
for field, typ in win_list._fields_:
#print ('%s=%d' % (field, getattr(disk_geometry, field)))
outDict[field]=getattr(win_list,field)
return outDict
def get_voltages():
FUNC=0x901
outDict={}
ioclt=CTL_CODE(FILE_DEVICE_UNKNOWN, FUNC, METHOD_BUFFERED, FILE_WRITE_ACCESS)
handle=_CreateFile('\\\\\.\PhysicalDrive0',GENERIC_WRITE,FILE_SHARE_WRITE,OPEN_EXISTING,ZERO)
win_list = OUTPUT_volt()
p_win_list = ctypes.pointer(win_list)
SIZE=ctypes.sizeof(OUTPUT_volt)
status, output = _DeviceIoControl(handle, ioclt , NULL, ZERO, p_win_list, SIZE)
for field, typ in win_list._fields_:
#print ('%s=%d' % (field, getattr(disk_geometry, field)))
outDict[field]=getattr(win_list,field)
return outDict
print(OUTPUT_temp._fields_)
Output:
[('Board Temp', <class 'ctypes.c_ulong'>), ('CPU Temp', <class 'ctypes.c_ulong'>), ('Board Temp2', <class 'ctypes.c_ulong'>), ('temp4', <class 'ctypes.c_ulong'>), ('temp5', <class 'ctypes.c_ulong'>)]
I tried this code, and it worked, but it needs admin (from here - https://stackoverflow.com/a/62936850/13710015):
import clr # the pythonnet module.
clr.AddReference(r'YourdllPath')
from OpenHardwareMonitor.Hardware import Computer
c = Computer()
c.CPUEnabled = True # get the Info about CPU
c.GPUEnabled = True # get the Info about GPU
c.Open()
while True:
for a in range(0, len(c.Hardware[0].Sensors)):
# print(c.Hardware[0].Sensors[a].Identifier)
if "/intelcpu/0/temperature" in str(c.Hardware[0].Sensors[a].Identifier):
print(c.Hardware[0].Sensors[a].get_Value())
c.Hardware[0].Update()
I tried this code, but it also needed admin (from here - https://stackoverflow.com/a/49909330/13710015):
import clr #package pythonnet, not clr
openhardwaremonitor_hwtypes = ['Mainboard','SuperIO','CPU','RAM','GpuNvidia','GpuAti','TBalancer','Heatmaster','HDD']
cputhermometer_hwtypes = ['Mainboard','SuperIO','CPU','GpuNvidia','GpuAti','TBalancer','Heatmaster','HDD']
openhardwaremonitor_sensortypes = ['Voltage','Clock','Temperature','Load','Fan','Flow','Control','Level','Factor','Power','Data','SmallData']
cputhermometer_sensortypes = ['Voltage','Clock','Temperature','Load','Fan','Flow','Control','Level']
def initialize_openhardwaremonitor():
file = 'OpenHardwareMonitorLib.dll'
clr.AddReference(file)
from OpenHardwareMonitor import Hardware
handle = Hardware.Computer()
handle.MainboardEnabled = True
handle.CPUEnabled = True
handle.RAMEnabled = True
handle.GPUEnabled = True
handle.HDDEnabled = True
handle.Open()
return handle
def initialize_cputhermometer():
file = 'CPUThermometerLib.dll'
clr.AddReference(file)
from CPUThermometer import Hardware
handle = Hardware.Computer()
handle.CPUEnabled = True
handle.Open()
return handle
def fetch_stats(handle):
for i in handle.Hardware:
i.Update()
for sensor in i.Sensors:
parse_sensor(sensor)
for j in i.SubHardware:
j.Update()
for subsensor in j.Sensors:
parse_sensor(subsensor)
def parse_sensor(sensor):
if sensor.Value is not None:
if type(sensor).__module__ == 'CPUThermometer.Hardware':
sensortypes = cputhermometer_sensortypes
hardwaretypes = cputhermometer_hwtypes
elif type(sensor).__module__ == 'OpenHardwareMonitor.Hardware':
sensortypes = openhardwaremonitor_sensortypes
hardwaretypes = openhardwaremonitor_hwtypes
else:
return
if sensor.SensorType == sensortypes.index('Temperature'):
print(u"%s %s Temperature Sensor #%i %s - %s\u00B0C" % (hardwaretypes[sensor.Hardware.HardwareType], sensor.Hardware.Name, sensor.Index, sensor.Name, sensor.Value))
if __name__ == "__main__":
print("OpenHardwareMonitor:")
HardwareHandle = initialize_openhardwaremonitor()
fetch_stats(HardwareHandle)
print("\nCPUMonitor:")
CPUHandle = initialize_cputhermometer()
fetch_stats(CPUHandle)
I am also fine with using C/C++ extensions with Python, portable command-line apps (which will be run with subprocess.Popen
), DLLs, and commands (which will be run with subprocess.Popen
).
Non-portable apps are not allowed.
An unprivileged user needs access to functionality only available by a privileged user in a secure manner.
Create an server-client interface where functionality is decoupled from the actual system as to prevent security issues (ie: don't just pipe commands or options directly from client for execution by the server).
Consider using gRPC for this server-client interface. If you haven't used gRPC before, here's an example of what this entails:
Create a temperature.proto
:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "temperature";
option java_outer_classname = "TemperatureProto";
option objc_class_prefix = "TEMP";
package temperature;
service SystemTemperature {
rpc GetTemperature (TemperatureRequest) returns (TemperatureReply) {}
}
message TemperatureRequest {
string name = 1;
}
message TemperatureReply {
string message = 1;
}
Compile the aforementioned with protoc
from protobuf
library.
python -m grpc_tools.protoc --proto_path=. temperature.proto --python_out=. --grpc_python_out=.
This will generate a file named temperature_pb2_grpc.py
, which is where you'll define functionality and response for GetTemperature, note, that you can implement logic branches contextual upon TemperatureRequest options passed from the client.
Once complete simply write and run a temperature_server.py
from your privileged user, and temperature_client.py
from your unprivileged user.
gRPC: https://grpc.io
gRPC QuickStart guide: https://grpc.io/docs/languages/ruby/quickstart/
This modifies the registry, use at your own risk.
This works with python:
app.py
filetherm.py
, example - C:\\...\\therm.py
app.py
User contributions licensed under CC BY-SA 3.0