[DONE]Ausgabe der CPU Auslastung

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

[DONE]Ausgabe der CPU Auslastung

Beitrag von tft »

Hallo,

ich habe einen Code ausgegraben:

Code: Alles auswählen

 ;- CPU-Auslastung-Ermittlung mit der PDH.DLL
;- "Helle" Klaus Helbing, 09.10.2012, tested with PB4.61 (x64), Win7/64 and PB4.61 (x86), Win-XP
;- Use Debug

If OpenLibrary(0, "PDH.DLL")                     ;MS-File in \System32
  SI.SYSTEM_INFO
  #PDH_CSTATUS_NEW_DATA = $1
  #PROCESSOR_ARCHITECTURE_AMD64 = $9

  GetSystemInfo_(@SI)                            ;Anzahl der Cores ermitteln
  AnzCore.l = SI\dwNumberOfProcessors
  Is64.i = SI\wProcessorArchitecture             ;w -> i
  Buffer.i = AllocateMemory(8 * AnzCore)
  CoreLast.d
  CoreLast64.d
  hQuery.l

  Prototype.l ProtoOpenQuery(Para1.l)
  Prototype.l ProtoCloseQuery(Para1.l)
  Prototype.l ProtoCollectData(Para1.l)
  Prototype.d ProtoAuslastung(Para1.l, Para2.l)
  Prototype.l ProtoAddCounter(Para1.l, Para2.i, Para3.i)

  Lang = GetSystemDefaultLangID_() & $FFFF
  Select Lang
    Case $407                                    ;GE
      P1$ = "Prozessor"
      P2$ = "Prozessorzeit" 
    Case $409                                    ;EN_US   ckeck it :-)!
      P1$ = "Processor"
      P2$ = "Processor Time"
    Case $40C                                    ;FR      check it :-)!
      P1$ = "Processeur"
      P2$ = "temps Processeur"
    ;.....  Other Languages

  EndSelect

  OpenQuery.ProtoOpenQuery = GetFunction(0, "PdhVbOpenQuery")
  CloseQuery.ProtoCloseQuery = GetFunction(0, "PdhCloseQuery")       ;PdhVbCloseQuery z.B. nicht für Server 2003 !
  CollectData.ProtoCollectData = GetFunction(0, "PdhCollectQueryData")
  AddCounter.ProtoAddCounter = GetFunction(0, "PdhVbAddCounter")
  Auslastung.ProtoAuslastung = GetFunction(0, "PdhVbGetDoubleCounterValue")
 
  RetVal = OpenQuery(@hQuery)
   
  If RetVal
    MessageRequester("Fehler !", "Aufruf von PdhVbOpenQuery fehlgeschlagen!")  ;Error-Message OpenQuery
    End
  EndIf

  For i = 0 To AnzCore - 1
    Proz$ = "\" + P1$ + "(" + Str(i) + ")\" + P2$ + " (%)"
    RetVal = AddCounter(hQuery, @Proz$, Buffer + (i << 2))
    If RetVal
      MessageRequester("Fehler !", "Aufruf von PdhVbAddCounter für Core"+ Str(i) + " fehlgeschlagen!")  ;Error-Message AddCounter
      ;End
    EndIf
  Next
 
  Repeat
    CollectData(hQuery)
    Auslastung$ = ""
    For i = 0 To AnzCore - 1
      CoreLast = Auslastung(PeekL(Buffer + (4 * i)), PeekL(Buffer + (4 * AnzCore) + (i << 2)))
      !movsd [v_CoreLast64],xmm0                 ;64-Bit-DLL: Float-/Double-Return-Value in XMM0!
      If Is64 = #PROCESSOR_ARCHITECTURE_AMD64
        CoreLast = CoreLast64
      EndIf
      Auslastung$ + "Core" + Str(i) + " = " + StrD(CoreLast, 2) + "%" + Space(20)
      If PeekL(Buffer + (4 * AnzCore) + (i << 2)) > #PDH_CSTATUS_NEW_DATA ;s.o.
        A = -1                                   ;war kein gültiger Wert
        Break
      EndIf     
    Next
    If A <> -1
      Debug Auslastung$
    EndIf
    Delay(1000)
  ForEver
 
  CloseQuery(hQuery)
  CloseLibrary(0)
EndIf
Der sollte eigentlich die CPU Auslastung anzeigen. Am Anfang gibt es die Fehlermeldung das die CPU Infos nicht gefunden werden können.
Ich denke das liegt daran, das dies ein sehr altes und für 32 Bit ausgelegtes beispiel ist.

Weis jemand wie ich das ändern muss?

Gruss TFT
Zuletzt geändert von tft am 09.08.2022 16:40, insgesamt 1-mal geändert.
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Ausgabe der CPU Auslastung

Beitrag von Bisonte »

Der Code von "Helle" hatte damals mit Win7 x64 funktioniert. Eventuell steht im Thread noch irgendetwas darueber...
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

Re: Ausgabe der CPU Auslastung

Beitrag von tft »

Hallo,

mittlerweile bin ich auf dieses Hier gestossen. Funktioniert mit 4 Kernen super ... aber warum nur 4, Ich sehe nicht das Problem.
Es geht wirklich nur für 4 Kerne. Ich brauche das. Um dynamisch bei erreichen der Auslastung eines Kernes einen Weiteren Prozess zu starten.
bei Mehr kernen wird auch keine Fehlermeldung ausgegeben. Ich habe einfach schon zu lange nix mehr gemacht. Und dann gleich sowas schwieriges.

Code: Alles auswählen

Procedure CPU_Auslastung (*Delay)
	
	
  Shared CPU_Last()
  Protected Core, OpenQuery.ProtoOpenQuery, CloseQuery.ProtoCloseQuery, CollectData.ProtoCollectData, AddCounter.ProtoAddCounter, Auslastung.ProtoAuslastung, RetVal, hQuery, i, Proz$, ASCII_String, CoreLast.d
	
	
	If OpenLibrary(0, "PDH.DLL")         ; MS-File in \System32
		Global SI.SYSTEM_INFO
		#PDH_CSTATUS_NEW_DATA = $1
		
		Core = AllocateMemory(64)        ; für max. 4 Cores, 0-15=Counter, 16-31=PdhStatus, 32-63=dblValue    oder Structure
		
	
		OpenQuery.ProtoOpenQuery 		= GetFunction(0, "PdhOpenQuery")
		CloseQuery.ProtoCloseQuery 		= GetFunction(0, "PdhCloseQuery")
		CollectData.ProtoCollectData 	= GetFunction(0, "PdhCollectQueryData")
		AddCounter.ProtoAddCounter 		= GetFunction(0, "PdhVbAddCounter")
		Auslastung.ProtoAuslastung 		= GetFunction(0, "PdhVbGetDoubleCounterValue")
		
		RetVal = OpenQuery(0, 1, @hQuery)
		If RetVal
			MessageRequester("Fehler !", "Aufruf von PdhOpenQuery fehlgeschlagen!") 
			End
		EndIf
		
		
		GetSystemInfo_(@SI)     				; Anzahl der Cores ermitteln
		CPU_Last(0) = SI\dwNumberOfProcessors	; ins Array speichern

		
		For i = 1 To SI\dwNumberOfProcessors
			Proz$ = "\Prozessor(" + Str(i-1) + ")\Prozessorzeit (%)"
			
			; konvertiert Proz$ in das ASCII-Format 
			ASCII_String = AllocateMemory(Len(Proz$) + 1)
			PokeS(ASCII_String, Proz$, -1, #PB_Ascii)
			
			RetVal = AddCounter(hQuery, ASCII_String, Core + ((i-1) << 2))
			If RetVal
				MessageRequester("Fehler !", "Aufruf von PdhVbAddCounter für Core"+ Str(i-1) + " fehlgeschlagen!") 
			EndIf
		Next 
		
		
		Repeat
			
			CollectData(hQuery) 

			For i = 1 To SI\dwNumberOfProcessors
				CoreLast.d = Auslastung(PeekL(Core + 4 * (i-1)), Core + 16 + ((i-1) << 2))
				If PeekL(Core + 16 + ((i-1) << 2)) > #PDH_CSTATUS_NEW_DATA
					Break
				Else
					CPU_Last(i) = CoreLast
				EndIf     
			Next
	
			Delay (*Delay)
			
		ForEver
	
		CloseQuery(@hQuery)
		CloseLibrary(0)
		
	EndIf	
	
EndProcedure
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
Benutzeravatar
tft
Beiträge: 605
Registriert: 08.09.2004 20:18
Computerausstattung: GTX Titan , i9 9900K , 32 GB Ram , 500 GB SSD , 3 ASUS FullHD Monitore and more
Wohnort: Dachsen
Kontaktdaten:

Re: Ausgabe der CPU Auslastung

Beitrag von tft »

Ich habe mittlerweile das hier gefunden.
Damit lässt sich die Prozessor last auslesen.
Auf drei meiner Rechner funktioniert es.
Der Orginal Code arbeitet mit der Debug Ausgabe.
Da diese Compiliert bei mir nicht funktioniert.
Auch nicht wenn ich das Programm im ADMIN Mode Starte.
Muss die Console Herhalten. Der Code beändet sich selber.

Probiert es doch bitte mal aus. Und Postet hier ob ihr Probleme hattet.

Code: Alles auswählen

#PDH_NO_DATA = $A00007D5              ;For CPU Usage %
#PDH_INVALID_HANDLE = $E0000BBC       ;For CPU Usage %

Prototype PdhLookupPerfNameByIndex(szMachineName.s, dwNameIndex.l, *szNameBuffer, *pcchNameBufferSize)
Global PdhLookupPerfNameByIndex.PdhLookupPerfNameByIndex, MemSize.l

Structure PDH_FMT_COUNTERVALUE        ;For CPU Usage %
  CStatus.l; As Long
  ;  case Cardinal of
  ;    0: (longValue: Integer);
  ;    1: (doubleValue: Double);
  ;    2: (largeValue: Int64);
  ;    3: (AnsiStringValue: PChar);
  ;    4: (WideStringValue: PWideChar);
  padding.l       ; As Long
  ulValueLow.l    ; As Long
  ulValueHigh.l   ; As Long
EndStructure
  
Procedure.s PDH_CounterName(CoreNum.s = "_Total")
  
  ;Good Result for English: \Processor(0)\% Processor Time
  
  Define *LPTSTR, Temp.s
  
  MemSize.l = 1024 ;Global Variable
  *LPTSTR = AllocateMemory(MemSize)
  If *LPTSTR
    If CoreNum.s = "-1"
      CoreNum.s = "_Total"
    EndIf
    If PdhLookupPerfNameByIndex(#Null$, 238, *LPTSTR, @MemSize) = 0
      Temp.s = "\" + PeekS(*LPTSTR, MemSize) + "(" + CoreNum.s + ")\"
      ;PrintN( PeekS(*LPTSTR, MemSize)
    EndIf
  EndIf
  FreeMemory(*LPTSTR)
  
  MemSize.l = 1024
  *LPTSTR = AllocateMemory(MemSize)
  If *LPTSTR
    If PdhLookupPerfNameByIndex(#Null$, 6, *LPTSTR, @MemSize) = 0
      Temp.s = Temp.s + PeekS(*LPTSTR, MemSize)
      ;PrintN( PeekS(*LPTSTR, MemSize)
    EndIf
  EndIf
  FreeMemory(*LPTSTR)
  
  PrintN( Temp.s)
  ProcedureReturn Temp.s
  
EndProcedure

#PerformanceLib = 88 ;Temp #

OpenConsole()

If OpenLibrary(#PerformanceLib, "pdh.dll")
CompilerIf #PB_Compiler_Unicode
  PdhLookupPerfNameByIndex = GetFunction(#PerformanceLib, "PdhLookupPerfNameByIndexW")
CompilerElse
  PdhLookupPerfNameByIndex = GetFunction(#PerformanceLib, "PdhLookupPerfNameByIndexA")
CompilerEndIf
EndIf 

hQuery.l
hCounter.l

RESULT.q = PdhOpenQuery_( 0, 1, @hQuery )

If result = ERROR_SUCCESS
  PrintN( Str(Result))
  PrintN( Str(hQuery))
  PrintN( "Good!")
  PrintN( "------")
EndIf

NewList ProcessorUsage.l()

CpuCount.l = CountCPUs(#PB_System_CPUs)

For AddC.l = 0 To CpuCount - 1
  RESULT = PdhAddCounter_(hQuery, PDH_CounterName(Str(Addc)), 0, @hCounter)
  AddElement(ProcessorUsage())
  ProcessorUsage() = hCounter
  ;If result = ERROR_SUCCESS
  ;  PrintN( Result
  ;  PrintN( hCounter
  ;  PrintN( "Good!"
  ;  PrintN( "------"
  ;EndIf
Next AddC

retcode.d
lpValue.PDH_FMT_COUNTERVALUE

RESULT = PdhCollectQueryData_(hQuery)
Delay(250)
PrintN( "--- Begin Tests ---")

For i=1 To 40  ;Test Loop, 40 times
  RESULT = PdhCollectQueryData_(hQuery)
  If result = ERROR_SUCCESS
    PrintN( "Good Query! Run # " + Str(i))
  ElseIf result = #PDH_INVALID_HANDLE
    PrintN( "PDH_INVALID_HANDLE")
  ElseIf result = #PDH_NO_DATA
    PrintN( "#PDH_NO_DATA")
  Else
    PrintN( "Error "+Hex(Result))
  EndIf
  megaRetcode.d = 0
  ForEach ProcessorUsage()
    hCounter = ProcessorUsage()
    PdhGetFormattedCounterValue_(hCounter, $200 | $8000, @dwType.l, @lpValue)
    CopyMemory(@lpValue\ulValueLow, @retcode, 8)
    PrintN( Str(Retcode) + "%")
    megaRetcode + retcode
  Next  
  PrintN( " = " + StrF(megaRetcode,1) + " / " + Str(CpuCount) + " = " + StrF(megaRetcode / CpuCount, 1) + "%")
  Delay(250)
TFT seid 1989 , Turgut Frank Temucin , Dachsen/Berlin/Antalya
Aktuelles Projekte : Driving School Evergarden
YouTube : Pure Basic to go
FaceBook : Temuçin SourceMAgic Games
DISCORD : SourceMagic
W10 , i9 9900K ,32 GB Ram , GTX Titan , 3 Monitore FHD
ARDUINO Freak :-)
Benutzeravatar
jacdelad
Beiträge: 341
Registriert: 03.02.2021 13:39
Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
Wohnort: Riesa
Kontaktdaten:

Re: [DONE]Ausgabe der CPU Auslastung

Beitrag von jacdelad »

Ähm...der Code funktioniert so nicht. Am Ende fehlt ein "Next". Wenn ich ihn im Debugger starte, es kommt ein "Overflow in the global data block" in Zeile 69. Ist das dein Code oder wo stammt der her?
Außerdem, und nimm mir das bitte nicht übel, dein Text im letzten Post ist ziemlich schwer zu verstehen...zu viele Punkte und keine Struktur.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Helle53
Beiträge: 1
Registriert: 09.08.2022 23:21

Re: [DONE]Ausgabe der CPU Auslastung

Beitrag von Helle53 »

Ich (Helle) wollte mich eigentlich früher hier einklinken, aber der Suff muss ausgerechnet die Gehirnzelle mit den PB-Anmeldedaten gelöscht haben. Also Neuanmeldung als "Helle53" und auf ein Neues :D !
Hier meine aktuelle Version von PDH:

Code: Alles auswählen

;Debugger an, aber ja nicht den Purifier einschalten wenn nicht das C-Backend genutzt wird! Sonst z.B. "Overflow in the global data block"!
If OpenLibrary(0, "PDH.DLL")                     ;MS-File in \System32
  #PDH_FMT_DOUBLE = 512
  AnzCore.i = CountCPUs(#PB_System_CPUs)
  Buffer.i = AllocateMemory((4 * AnzCore) + 8 + (8 * AnzCore))  ;(4*AnzCore)=hCounter, 8=Rückgabe-Status, (8*AnzCore)=Rückgabe-Double-Werte
  ErrorCode.i
  hQuery.l
  
  Prototype.l ProtoOpenQuery(Para1.l, Para2.l, Para3.i)
  Prototype.l ProtoCloseQuery(Para1.l)
  Prototype.l ProtoCollectData(Para1.l)
  Prototype.d ProtoAuslastung(Para1.l, Para2.l, Para3.l, Para4.i)
  Prototype.l ProtoAddCounter(Para1.l, Para2.l, Para3.l, Para4.i)

  OpenQuery.ProtoOpenQuery = GetFunction(0, "PdhOpenQuery")
  CloseQuery.ProtoCloseQuery = GetFunction(0, "PdhCloseQuery")
  CollectData.ProtoCollectData = GetFunction(0, "PdhCollectQueryData")
  AddCounter.ProtoAddCounter = GetFunction(0, "PdhAddEnglishCounterW")         ;ist so sprachunabhängig! W für Unicode!
  Auslastung.ProtoAuslastung = GetFunction(0, "PdhGetFormattedCounterValue")
  
  RetVal = OpenQuery(0, 1, @hQuery)
  If RetVal
    MessageRequester("Fehler !", "Aufruf von PdhOpenQuery fehlgeschlagen!")    ;Error-Message OpenQuery
    End
  EndIf
  
  For i = 0 To AnzCore - 1
    Proz$ = "\Processor(" + Str(i) + ")\% Processor Time"       ;englisch, s.o.
    RetVal = AddCounter(hQuery, @Proz$, 1, Buffer + (i << 2))   ;Counter-Handle
    If RetVal
      MessageRequester("Fehler !", "Aufruf von PdhAddCounter für Core" + Str(i) + " fehlgeschlagen (Fehler-Code $" + Hex(RetVal) + ")!")   ;Error-Message AddCounter
      If RetVal = $C0000BB8            ;PDH_CSTATUS_NO_OBJECT, dürfte der häufigste Fehler sein. Kann evtl. auch bei anderen Fehlern ausgeführt werden
        MessageRequester("Fehlerbehebung", "Auf der Kommando-Zeile mit Administrator-Rechten einmalig ausführen: lodctr /r")
      EndIf
      End
    EndIf
  Next
    
  Repeat
    CollectData(hQuery) 
    Auslastung$ = ""
    For i = 0 To AnzCore - 1
      Auslastung(PeekL(Buffer + (i << 2)), #PDH_FMT_DOUBLE, 0, Buffer + (4 * AnzCore) + (i << 3))  ;Buffer + (4 * i) =hCounter
      Auslastung$ + "Core" + Str(i) + " = " + StrD(PeekD(Buffer + 8 + (4 * AnzCore) + (i << 3)), 2) + "%" + Space(4)   
    Next
     ErrorCode = PeekQ(Buffer + (4 * AnzCore))
    If ErrorCode = 0
      Debug Auslastung$
     Else
      Debug "Wert war Käse! (Fehler-Code $" + Hex(ErrorCode) + ")"   ;bei Programm-Start normal, Ruhe bewahren ;-)
    EndIf   
    Delay(500)
  ForEver          ;irgendeine Abbruch-Bedingung muss der User einfügen
  
  CloseQuery(hQuery)
  CloseLibrary(0)
EndIf
Kann hiermit kurz getestet werden:

Code: Alles auswählen

a = 1
For j = 1 To CountCPUs(#PB_System_CPUs)
  SetThreadAffinityMask_(GetCurrentThread_(), a)
  For i = 0 To 100000000
    k + 1          ;irgendwelcher Schnulli
  Next
  a << 1
Next
Übrigens sind die korrekten Werte #PDH_NO_DATA = $800007D5 und #PDH_INVALID_HANDLE = $C0000BBC.

Gruß
Helle
Antworten