![]() |
Re: Cpu usage EINZELNER PROZESSE ermitteln
super, bin schon sehr gespannt.
@Catbytes : ich gehe mal davon aus, dass ich das Prozesshandle übergeben muss oder? Wieso bekomme ich dann teilweise negative Werte? Und warum (wenn die Auslastung bei 100% ist) verringert sich die Auslastung wieder auf 0% solange ich das Fenster hin und herschiebe? |
Re: Cpu usage EINZELNER PROZESSE ermitteln
Das ist der Zauber von Application.ProcessMessages() ;)
|
Re: Cpu usage EINZELNER PROZESSE ermitteln
Liste der Anhänge anzeigen (Anzahl: 2)
Die Berechnung anhand der Werte solltest du CatBytes' Beispiel entnehmen. Ansonsten gibt es hier Code, der dir für beliebige Prozesse anhand der PID (also ohne Handle) die entsprechenden Zeiten anzeigt. Einzig die ExitTime wird von meiner Funktion nicht beachtet, da man die wirklich nur mit Handle rausbekommt (und sie für deine Berechnung auch nicht wichtig ist).
Die Units, vom JEDI-Apilib-Projekt brauchst du nach wie vor (es gibt übrigens eine aktualisierte Version von JwaWinType und JwaNative), die du dir und also runterladen solltest. Aus der Funktion CallBackProcess() solltest du das Writeln() entfernen, sobald du es getestet hast. Weil es ja so 1. nur in Konsolenprogrammen funktioniert und 2. nur zum Testen da war. Die wichtige Funktion für dich ist GetProcessTimesByPid()! Alle anderen brauchen dich nicht wirklich zu interessieren. Falls sie es doch tun, kann ich es noch ein wenig erläutern ;) ... Als Test gibt dieses Miniprogramm einfach aus, wann der Prozess mit der hardcodeten PID gestartet wurde. Vorzugsweise sollte die PID natürlich existieren ;) Der Code ist PUBLIC DOMAIN, darf aber natürlich auch unter einer beliebigen OSI-zertifizierten Lizenz benutzt werden - in diesem Falle ist "Copyright (c) 2005 by Mephistopheles" anzugeben. Für die Benutzung der entsprechenden Units gelten die dort angegebenen Lizenzvereinbarungen (üblicherweise MPL für JEDI). Kleines Projekt mit den Funktionen:
Delphi-Quellcode:
BTW: Hatte da einen dummen Fehler drin, den ich jetzt per Debugger gefunden hatte. Ursprüngliche war meine Callback-Funktion als lokale Funktion deklariert. Das ist natürlich tötlich, weil mit jedem Aufruf der Callback sich auch der Stackframe ändert. Logischerweise werden also falsche Pointerwerte vom Stack geholt und es wird versucht auf diese zu schreiben ... *plonk* -> AV! ... naja, die Lehre daraus: Niemals eine Callbackfunktion, die von einer dritten Funktion aufgerufen wird als lokale Funktion deklarieren. Hätte ich eigentlich gleich drauf kommen müssen. Übrigens: deshalb die Kopfstände mit PProcessTimeRecord usw.!
program ProcessTimesNoHandle;
{$APPTYPE CONSOLE} uses Windows, SysUtils, JwaNtStatus, JwaWinType, JwaNative; type TCallBackProcess = function(ps: PSYSTEM_PROCESSES; dwUserData: DWORD): BOOL; stdcall; PProcessTimeRecord = ^TProcessTimeRecord; TProcessTimeRecord = record PID: DWORD; CreationTime, KernelTime, UserTime: LARGE_INTEGER; end; function ListProcesses(Callback: TCallBackProcess; dwUserData: DWORD): Boolean; var Status: NTSTATUS; Buffer: PVOID; TempBuf: PSYSTEM_PROCESSES; BufLen: ULONG; const MinQuerySize = $10000; begin Result := False; BufLen := MinQuerySize; Buffer := RtlAllocateHeap(NtpGetProcessHeap(), HEAP_ZERO_MEMORY, BufLen); if (Assigned(Buffer)) then try Status := NtQuerySystemInformation( SystemProcessesAndThreadsInformation, Buffer, BufLen, nil); while (Status = STATUS_INFO_LENGTH_MISMATCH) do begin // Double the size to allocate BufLen := BufLen * 2; TempBuf := RtlReAllocateHeap(NtpGetProcessHeap(), HEAP_ZERO_MEMORY, Buffer, BufLen); if (not Assigned(TempBuf)) then Exit; // And free "Buffer" inside finally clause // Else assign the TempBuf to Buffer Buffer := TempBuf; // Try to query info again Status := NtQuerySystemInformation( SystemProcessesAndThreadsInformation, Buffer, BufLen, nil); end; // TempBuf used for pointer arithmetics TempBuf := Buffer; if (NT_SUCCESS(Status)) then begin while (True) do begin if (Assigned(Callback)) then if (not CallBack(TempBuf, dwUserData)) then // Exit loop if the callback signalled to do so. Break; // Break if there is no next entry if (TempBuf^.NextEntryDelta = 0) then Break; // Else go to next entry in list TempBuf := PSYSTEM_PROCESSES(DWORD(TempBuf) + TempBuf^.NextEntryDelta); end; Result := True; end; finally if (Assigned(Buffer)) then RtlFreeHeap(NtpGetProcessHeap(), 0, Buffer); end; end; // This MUST NOT be a local function function CallBackProcess(ps: PSYSTEM_PROCESSES; ProcessTimeRecord: PProcessTimeRecord): BOOL; stdcall; begin Result := True; if (Assigned(ps)) then if (ps^.ProcessId = ProcessTimeRecord^.PID) then begin ProcessTimeRecord^.CreationTime := ps^.CreateTime; ProcessTimeRecord^.KernelTime := ps^.KernelTime; ProcessTimeRecord^.UserTime := ps^.UserTime; // FIXME: This is for debugging only. Of course not needed in production code Writeln('PID = ', ps^.ProcessId, ' - parent = ', ps^.InheritedFromProcessId); // Stop going through the list Result := False; end; end; // Instead of only taking the times, it would be easier and more effective to // take all information directly from the SYSTEM_PROCESS structures in the // callback! function GetProcessTimesByPid( PID: DWORD; var lpCreationTime: Windows.FILETIME; var lpKernelTime: Windows.FILETIME; var lpUserTime: Windows.FILETIME ): BOOL; stdcall; var times: TProcessTimeRecord; begin times.PID := PID; // PID to search for // We need to pass a pointer here! Result := ListProcesses(@CallBackProcess, DWORD(@times)); lpCreationTime := Windows.FILETIME(times.CreationTime); lpKernelTime := Windows.FILETIME(times.KernelTime); lpUserTime := Windows.FILETIME(times.UserTime); end; var lpCreationTime, lpKernelTime, lpUserTime: Windows.FILETIME; cst: SYSTEMTIME; begin // Hardcoded PID for testing. This should be called for each PID found if (GetProcessTimesByPid(2588, lpCreationTime, lpKernelTime, lpUserTime)) then begin FileTimeToSystemTime(lpCreationTime, cst); Writeln(Format('Process created: %.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.3d', [cst.wYear, cst.wMonth, cst.wDay, cst.wHour, cst.wMinute, cst.wSecond, cst.wMilliseconds])); end; Readln; end. PS: Sorry, daß ich dich warten lassen habe. Bin aktuell etwas im Streß (auch außerhalb der DP ;)). PPS: Windows.FILETIME wird explizit benutzt, damit es keinen Konflikt mit dem gleichnamigen (und gleichwertigen) Typen aus der JwaNative.pas (bzw. den zugehörigen Units) beim Kompilieren gibt. PPPS: Im Anhang das Projekt ohne die besagten Units. Die muß man sich bitte selber ![]() |
Re: Cpu usage EINZELNER PROZESSE ermitteln
Leider bekomme ich beim Kompilieren folgende Fehler auch wenn ich die Units einbinde:
[Error] ProcessTimesNoHandle.dpr(32): Undeclared identifier: 'RtlAllocateHeap' [Error] ProcessTimesNoHandle.dpr(32): Undeclared identifier: 'NtpGetProcessHeap' [Error] ProcessTimesNoHandle.dpr(32): Undeclared identifier: 'HEAP_ZERO_MEMORY' [Error] ProcessTimesNoHandle.dpr(44): Undeclared identifier: 'RtlReAllocateHeap' [Error] ProcessTimesNoHandle.dpr(76): Undeclared identifier: 'RtlFreeHeap' |
Re: Cpu usage EINZELNER PROZESSE ermitteln
... die sich mein Lieblings-Mod-Osterhasi aus dem CVS oder als letztes Release (ZIP oder so) runtergeladen hat?
Vertrau mir, ich weiß was ich sage, wenn ich sage: CVS-Version. Du kannst dich gern in der History von den Änderungen seit dem letzten Release (als kompaktes Paket irgendwo auf der Seite verfügbar) überzeugen (u.a. Wachstum um über 700%!). Dann verstehst du warum es nicht geht. |
Re: Cpu usage EINZELNER PROZESSE ermitteln
Habe an den obigen Beitrag die Units noch zusätzlich angehangen, falls es Probleme mit dem CVS gibt. Die Units wurden gestern das letzte Mal aktualisiert eingecheckt. Es ist also taufrisch und noch knusprig-warm.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz