Seite 1 von 1

[Module] [Windows] Hardware-Monitoring (Aida64)

Verfasst: 02.11.2015 16:59
von Bisonte
aida, aida64, sensor

Hallo.

Hier ein Modul, um die Sensordaten von Aida64 Extreme auszulesen. Es ist nur für Windows, da
1. Aida64Extrem und 2. API benutzt wird.

Benötigt natürlich Aida64 Extreme (weiss nicht ob es auch mit der 'nicht Extreme' Version klappt),
dort muss in den Einstellungen 'Externe Applikationen' bei Hardware Überwachung "Aktiviere Shared Memory"
ausgewählt sein ... und natürlich auch ein paar Sensoren.

Im Fall des Beispiels muss Temperatur-CPU Package (TCPUPKG) und System-CPUAuslastung (SCPUUTI) ausgewählt sein,
damit auch etwas angezeigt wird.

Die Werte der Sensoren wird in einer Liste gespeichert. Diese sollte nur zum LESEN benutzt werden.
Man kann aber auch die Werte einzelnd abfragen...

Verbesserungsvorschläge ? Immer her damit !

Hier habe ich das ganze mit Stringoperationen auseinandergezerrt, da die Ausgabe von Aida ein String in einem XML ähnlichen Format ist.

Bei meinen Tests hat die Abfrage der Werte 5ms mit Debugger gedauert. Evt. gehts ja anders noch schneller ?
XML ? ASM ? Einfach nur anders als hier gelöst ?

P.S. : Threadsafe muss in den Optionen eingetellt sein... na dann... gehts los ;)

Code: Alles auswählen

;: ############################################################################
;: # 
;: # Module     : Aida64
;: # 
;: # Author     : Bisonte
;: # Date       : 02. November 2015
;: # COpt.      : THREAD
;: # PB Version : 5.40 LTS Final
;: # 
;: ############################################################################
;: 
;: To get the SharedMemory SensorData of Aida64
;: Req. CompilerOption Threadsafe
;: and, of course, Aida64 with Shared Memory enabled
;: (and some sensors marked)
;: 
;: Tested with Aida64 Extrem on Win10 Pro x64
;: The Demo shows CPU Package Temperature and CPU Utilization if marked
;: in Aida64

DeclareModule Aida64
  
  EnableExplicit
  
  #AIDA64_SensorValues = "AIDA64_SensorValues"
  
  Structure aida_sensordata
    category.s
    id.s
    label.s
    value.s
  EndStructure
  
  Global NewList Aida64Sensor.aida_sensordata()
  
  Declare.i StartAida64(Delay = 1000, CustomEvent = #PB_Event_FirstCustomValue)
  Declare.i StopAida64()
  Declare.s GetSensorValueOverID(ID.s)
  Declare.s GetSensorValueOverLabel(Label.s)
  
EndDeclareModule
Module        Aida64

  CompilerIf Not #PB_Compiler_Thread
    CompilerError "Module : 'Aida64' requires ThreadSafe Compileroption!"
  CompilerEndIf  
  
  Global Mutex = CreateMutex()
  Global Thread = #False
  Global Halt   = #False
  Global CEvent = #PB_Event_FirstCustomValue
  
  Procedure.s _GetString(String.s, Before.s, After.s)
    
    Protected Result.s
    Protected Start, Stop
    
    Start = FindString(String, Before)
    Stop  = FindString(String, After)
    
    If Start > 0 And Stop > Start
      Result = Mid(String, Start + Len(Before), (Stop-Len(After)) - Start + 1)  
    EndIf
    
    ProcedureReturn Result
    
  EndProcedure  
  Procedure GetAidaSensorList(Delay)
    
    Protected handle, *Mem, Size, Result.s, String.s
    
    While Halt <> #True
      
      LockMutex(mutex)
      
      ClearList(Aida64Sensor())
      
      handle = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, 0, "AIDA64_SensorValues")
      If handle
        *Mem = MapViewOfFile_(handle, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
        If *Mem
          Size = MemoryStringLength(*Mem, #PB_Ascii)
          Result = PeekS(*Mem, Size, #PB_Ascii)
          While Result <> ""
            String = Left(Result, FindString(Result, ">"))
            String + _GetString(Result, Left(Result, FindString(Result, ">")), "</" + Mid(Left(Result, FindString(Result, ">")), 2))
            String + "</" + Mid(Left(Result, FindString(Result, ">")), 2)
            AddElement(Aida64Sensor())
            Aida64Sensor()\category = Left(String, FindString(String, ">"))
            Aida64Sensor()\id  = _GetString(String, "<id>", "</id>")
            Aida64Sensor()\label = _GetString(String, "<label>", "</label>")
            Aida64Sensor()\value = _GetString(String, "<value>", "</value>")
            Result = Mid(Result, Len(String) + 1)
          Wend
          UnmapViewOfFile_(*Mem)
        EndIf
        CloseHandle_(handle)
      EndIf
      
      UnlockMutex(mutex)
      
      PostEvent(CEvent)
      
      Delay(Delay)

    Wend
    
  EndProcedure
  Procedure StartAida64(Delay = 1000, CustomEvent = #PB_Event_FirstCustomValue)
    
    Protected Result
    
    If IsThread(Thread) : Halt = #True : EndIf
    
    CEvent = CustomEvent
    Thread = CreateThread(@GetAidaSensorList(), Delay)
    If Thread
      ProcedureReturn #True
    EndIf
    
    ProcedureReturn #False
    
  EndProcedure
  Procedure StopAida64()
    If IsThread(Thread) : Halt = #True : EndIf
  EndProcedure
  
  Procedure.s GetSensorValueOverID(ID.s)
    Protected Result.s
    ForEach Aida64Sensor()
      If Aida64Sensor()\id = ID
        Result = Aida64Sensor()\value
        Break
      EndIf
    Next
    ProcedureReturn Result
  EndProcedure
  Procedure.s GetSensorValueOverLabel(Label.s)
    Protected Result.s
    ForEach Aida64Sensor()
      If Aida64Sensor()\label = Label
        Result = Aida64Sensor()\value
        Break
      EndIf
    Next
    ProcedureReturn Result
  EndProcedure  
  
EndModule

CompilerIf #PB_Compiler_IsMainFile
  
  EnableExplicit
  
  #AIDA64_DataReady = #PB_Event_FirstCustomValue
  
  Define Event, CPUTEMP, CPUUTIL
  
  OpenWindow(0, 0, 0, 100, 150, "Aida64", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  CanvasGadget(1, 10, 10, 50, 100)
  TextGadget(2, 10, 110, 20, 25, "", #PB_Text_Center)
  TextGadget(3, 40, 110, 20, 25, "", #PB_Text_Center)

  Aida64::StartAida64(500, #AIDA64_DataReady)
  
  Repeat
    Event = WaitWindowEvent()
    
    Select Event
      Case #PB_Event_CloseWindow
        Aida64::StopAida64()
        Break
      Case #AIDA64_DataReady
        If StartDrawing(CanvasOutput(1))
          CPUTEMP = Val(Aida64::GetSensorValueOverID("TCPUPKG"))
          CPUUTIL = Val(Aida64::GetSensorValueOverID("SCPUUTI"))
          Box(0, 0, OutputWidth(), OutputHeight(), GetSysColor_(#COLOR_BTNFACE))
          DrawingMode(#PB_2DDrawing_Gradient)
          BackColor(#Red) : FrontColor(#Green)
          LinearGradient(0, 0, 20, 100)
          Box(0, 100, 20, -CPUTEMP, 0)
          Box(30, 100, 20, -CPUUTIL, 0)
          StopDrawing()
        EndIf
        SetGadgetText(2, Str(CPUTEMP))
        SetGadgetText(3, Str(CPUUTIL) + "%")
        
    EndSelect
    
  ForEver

CompilerEndIf

Re: [Module] [Windows] Aida64

Verfasst: 02.11.2015 18:41
von Kiffi
Hallo Bisonte,

(ich möchte Deinen Thread nicht kapern, deswegen habe ich meinen Code hierhin ausgelagert)

Ich würde es mit WMI machen. Ist wahrscheinlich nicht so performant, kostet dafür aber nichts. ;-)

Grüße ... Peter

Re: [Module] [Windows] Aida64

Verfasst: 02.11.2015 20:22
von Bisonte
Nunja... mir ging es da hauptsächlich um die Hardware-Überwachung.
Also Temperaturfühler, Lüftergeschwindigkeiten, CPU Taktung usw. und die
bekomme ich, soweit ich weiss, nicht per WMI.

Das mit der CPU Auslastung war in meinem Beispiel natürlich nur exemplarisch, um zu zeigen, wie es geht.

Was den Kostenfaktor betrifft... Ich glaube HWInfo kann das auch und macht es womöglich auf gleiche Weise. Mal sehen ob ich damit
was anstellen kann ;)

Re: [Module] [Windows] Aida64

Verfasst: 02.11.2015 20:44
von Kiffi
Sorry, ich wollte Deinen Code nicht herabwürdigen. Wollte mit WMI nur eine kostenfreie Alternative aufzeigen. WMI ist die eierlegende Wollmilchsau, wenn es darum geht, Informationen rund um den Rechner zu ermitteln (inklusive Temperaturfühler, Lüftergeschwindigkeiten, CPU Taktung, ...).

Grüße ... Peter

Re: [Module] [Windows] Aida64

Verfasst: 02.11.2015 21:13
von Bisonte
Auch Temperatur ? Alle Achtung. Wenn Du mir jetzt nur noch verraten kannst, wo ich nachlesen kann, wie man das ganze anwendet ....

Das mit HWInfo hat sich erledigt. Der Author möchte von jedem der seine .dll nutzen möchte eine Email mit Projektbeschreibung usw. haben.
Da ist das für ein Open Source Modul wohl denkbar ungünstig ;)

Re: [Module] [Windows] Aida64

Verfasst: 03.11.2015 00:55
von Kiffi
Bisonte hat geschrieben:Auch Temperatur ? Alle Achtung. Wenn Du mir jetzt nur noch verraten kannst, wo ich nachlesen kann, wie man das ganze anwendet ....
ursprünglich wollte ich MSAcpi_ThermalZoneTemperature oder Win32_TemperatureProbe vorschlagen, bis ich bemerkte, dass diese Abfragen wohl nicht auf jedem Rechner funktionieren (auf meinem Büro-Rechner: ja; auf meinem Heim-Rechner: nein), was natürlich Käse ist.

Dann fand ich aber dieses kleine Schmuckstück hier: OpenHardwareMonitor.

Bild

OpenHardwareMonitor speist seine ermittelten Daten in das WMI ein, welche man dann wieder recht einfach auslesen kann:

Code: Alles auswählen

EnableExplicit

Define VbScript.s
Define VBS
Define Xml.s

VbScript.s = "strComputer = ''.''" + #CRLF$ + 
             "Set objWMIService = GetObject(''winmgmts:{impersonationLevel=impersonate}!\\'' & strComputer & ''\root\OpenHardwareMonitor'')" + #CRLF$ + 
             "Set colItems = objWMIService.ExecQuery(''Select * From Hardware'')" + #CRLF$ + 
             "Output = ''<OpenHardwareMonitor>''" + #CRLF$ + 
             "Output = Output & ''<Hardware>''" + #CRLF$ + 
             "For Each objItem in colItems" + #CRLF$ + 
             "  Output = Output & ''<element>''" + #CRLF$ + 
             "  Output = Output & ''<HardwareType>'' & objItem.HardwareType & ''</HardwareType>''" + #CRLF$ + 
             "  Output = Output & ''<Identifier>'' & objItem.Identifier & ''</Identifier>''" + #CRLF$ + 
             "  Output = Output & ''<InstanceId>'' & objItem.InstanceId & ''</InstanceId>''" + #CRLF$ + 
             "  Output = Output & ''<Name>'' & objItem.Name & ''</Name>''" + #CRLF$ + 
             "  Output = Output & ''<Parent>'' & objItem.Parent & ''</Parent>''" + #CRLF$ + 
             "  Output = Output & ''<ProcessId>'' & objItem.ProcessId & ''</ProcessId>''" + #CRLF$ + 
             "  Output = Output & ''</element>''" + #CRLF$ + 
             "Next" + #CRLF$ + 
             "Output = Output & ''</Hardware>''" + #CRLF$ + 
             "Set colItems = objWMIService.ExecQuery(''SELECT * FROM Sensor'')" + #CRLF$ + 
             "Output = Output & ''<Sensor>''" + #CRLF$ + 
             "For Each objItem in colItems" + #CRLF$ + 
             "  Output = Output & ''<element>''" + #CRLF$ + 
             "  Output = Output & ''<Identifier>'' & objItem.Identifier & ''</Identifier>''" + #CRLF$ + 
             "  Output = Output & ''<Index>'' & objItem.Index & ''</Index>''" + #CRLF$ + 
             "  Output = Output & ''<InstanceId>'' & objItem.InstanceId & ''</InstanceId>''" + #CRLF$ + 
             "  Output = Output & ''<Max>'' & objItem.Max & ''</Max>''" + #CRLF$ + 
             "  Output = Output & ''<Min>'' & objItem.Min & ''</Min>''" + #CRLF$ + 
             "  Output = Output & ''<Name>'' & objItem.Name & ''</Name>''" + #CRLF$ + 
             "  Output = Output & ''<Parent>'' & objItem.Parent & ''</Parent>''" + #CRLF$ + 
             "  Output = Output & ''<ProcessId>'' & objItem.ProcessId & ''</ProcessId>''" + #CRLF$ + 
             "  Output = Output & ''<SensorType>'' & objItem.SensorType & ''</SensorType>''" + #CRLF$ + 
             "  Output = Output & ''<Value>'' & objItem.Value & ''</Value>''" + #CRLF$ + 
             "  Output = Output & ''</element>''" + #CRLF$ + 
             "Next" + #CRLF$ + 
             "Output = Output & ''</Sensor>''" + #CRLF$ + 
             "Output = Output & ''</OpenHardwareMonitor>''" + #CRLF$ + 
             "WScript.StdOut.Writeline Output" 

VbScript = ReplaceString(VbScript, "''", Chr(34))

CreateFile(0, GetTemporaryDirectory() + "cpuinfo.vbs")
WriteString(0, VbScript)
CloseFile(0)

VBS = RunProgram("wscript", GetTemporaryDirectory() + "cpuinfo.vbs", "", #PB_Program_Open | #PB_Program_Read)

If VBS
  Xml = ReadProgramString(VBS)
  CloseProgram(VBS)
Else
  Debug "!RunProgram"
EndIf

Structure sSensorElement
  Parent.s
  Name.s
  InstanceId.s
  Value.s
  Min.s
  Index.s
  Max.s
  Identifier.s
  ProcessId.s
  SensorType.s
EndStructure

Structure sHardwareElement
  HardwareType.s
  Name.s
  InstanceId.s
  Identifier.s
  ProcessId.s
EndStructure

Structure OpenHardwareMonitor
  List Hardware.sHardwareElement()
  List Sensor.sSensorElement()
EndStructure

If ParseXML(0, Xml) And XMLStatus(0) = #PB_XML_Success
  
  Define OpenHardwareMonitor.OpenHardwareMonitor

  ExtractXMLStructure(MainXMLNode(0), @OpenHardwareMonitor, OpenHardwareMonitor)
  
  FreeXML(0)
  
  Debug "Hardware:"
  Debug "========="
  
  ForEach OpenHardwareMonitor\Hardware()
    Debug "HardwareType: " + OpenHardwareMonitor\Hardware()\HardwareType
    Debug "Identifier: " + OpenHardwareMonitor\Hardware()\Identifier
    Debug "InstanceId: " + OpenHardwareMonitor\Hardware()\InstanceId
    Debug "Name: " + OpenHardwareMonitor\Hardware()\Name
    Debug "ProcessId: "+ OpenHardwareMonitor\Hardware()\ProcessId
    Debug "-----"
  Next
  
  Debug "Sensor:"
  Debug "======="
  
  ForEach OpenHardwareMonitor\Sensor()
    Debug "Identifier: " + OpenHardwareMonitor\Sensor()\Identifier
    Debug "Index: " + OpenHardwareMonitor\Sensor()\Index
    Debug "InstanceId: " + OpenHardwareMonitor\Sensor()\InstanceId
    Debug "Max: " + OpenHardwareMonitor\Sensor()\Max
    Debug "Min: " + OpenHardwareMonitor\Sensor()\Min
    Debug "Name: " + OpenHardwareMonitor\Sensor()\Name
    Debug "Parent: " + OpenHardwareMonitor\Sensor()\Parent
    Debug "ProcessId: " + OpenHardwareMonitor\Sensor()\ProcessId
    Debug "SensorType: " + OpenHardwareMonitor\Sensor()\SensorType
    Debug "Value: " + OpenHardwareMonitor\Sensor()\Value
    Debug "-----"
  Next
  
Else
  Debug XMLError(0)
EndIf
Grüße ... Peter