![]() |
Delphi-Version: XE5
CPU und Memory Nutzung eines Prozesses
Hallo Zusammen,
ich bastele gerade an einem Programm mit dem ich die CPU und Hauptspeicher Nutzung eines benannten Prozessen ermitteln möchte. Folgende Funktionen habe ich hierzu im Netz gefunden
Delphi-Quellcode:
Für die Ermittlung des Memory Verbrauchs habe ich 2 Funktionen die ich beide versucht habe.
function ShowMemoryUsage(ProcessId: DWORD): DWORD;
var hProcess: THandle; PMC: PPROCESS_MEMORY_COUNTERS; cb: Integer; begin Result := 0; // cb := SizeOf(PMC); // = 4; cb := SizeOf(PMC^); GetMem(PMC, cb); try PMC^.cb := cb; hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessId); begin if ( hProcess = 0 ) then Exit; // if ( GetProcessMemoryInfo(hProcess, @PMC, SizeOf(PMC)) ) then if ( GetProcessMemoryInfo(hProcess, PMC, SizeOf(PMC^)) ) then //Result := (PMC^.WorkingSetSize Div 1024) Result := (PMC^.WorkingSetSize) else begin returntext := 'CRITICAL - ' + SysErrorMessage(GetLastError); returncode := 1; end; end; finally CloseHandle(hProcess); FreeMem(PMC, SizeOf(_PROCESS_MEMORY_COUNTERS)); end; end; function GetProcessMemorySize(sProcessName: string; var nMemSize: Cardinal): Boolean; var l_nWndHandle, l_nProcID, l_nTmpHandle: HWND; l_pPMC: PPROCESS_MEMORY_COUNTERS; l_pPMCSize: Cardinal; begin l_nWndHandle := FindWindow(nil, PChar(sProcessName)); if l_nWndHandle = 0 then begin writeln('fehler'); Result := False; Exit; end; l_pPMCSize := SizeOf(PROCESS_MEMORY_COUNTERS); GetMem(l_pPMC, l_pPMCSize); l_pPMC^.cb := l_pPMCSize; GetWindowThreadProcessId(l_nWndHandle, @l_nProcID); l_nTmpHandle := OpenProcess(PROCESS_ALL_ACCESS, False, l_nProcID); if (GetProcessMemoryInfo(l_nTmpHandle, l_pPMC, l_pPMCSize)) then nMemSize := l_pPMC^.WorkingSetSize else begin writeln('fehler'); nMemSize := 0; end; FreeMem(l_pPMC); CloseHandle(l_nTmpHandle); Result := True; end; // Get ProcessID By ProgramName (Include Path or Not Include) function GetPIDByProgramName(const APName: string): THandle; var isFound: boolean; AHandle, AhProcess: THandle; ProcessEntry32: TProcessEntry32; APath: array[0..MAX_PATH] of char; begin try Result := 0; AHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); ProcessEntry32.dwSize := Sizeof(ProcessEntry32); isFound := Process32First(AHandle, ProcessEntry32); while isFound do begin AhProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, ProcessEntry32.th32ProcessID); GetModuleFileNameEx(AhProcess, 0, @APath[0], sizeof(APath)); if (UpperCase(StrPas(APath)) = UpperCase(APName)) or (UpperCase(StrPas(ProcessEntry32.szExeFile)) = UpperCase(APName)) then begin Result := ProcessEntry32.th32ProcessID; break; end; isFound := Process32Next(AHandle, ProcessEntry32); CloseHandle(AhProcess); end; finally CloseHandle(AHandle); end; end; function GetCpuUsage(PID:cardinal):single; const cWaitTime=750; var h : Cardinal; mCreationTime,mExitTime,mKernelTime, mUserTime:_FILETIME; TotalTime1,TotalTime2:int64; begin {We need to get a handle of the process with PROCESS_QUERY_INFORMATION privileges.} h:=OpenProcess(PROCESS_QUERY_INFORMATION,false,PID); {We can use the GetProcessTimes() function to get the amount of time the process has spent in kernel mode and user mode.} GetProcessTimes(h,mCreationTime,mExitTime,mKernelTime,mUserTime); TotalTime1:=int64(mKernelTime.dwLowDateTime or (mKernelTime.dwHighDateTime shr 32)) + int64(mUserTime.dwLowDateTime or (mUserTime.dwHighDateTime shr 32)); {Wait a little} Sleep(cWaitTime); GetProcessTimes(h,mCreationTime,mExitTime,mKernelTime,mUserTime); TotalTime2:=int64(mKernelTime.dwLowDateTime or (mKernelTime.dwHighDateTime shr 32)) + int64(mUserTime.dwLowDateTime or (mUserTime.dwHighDateTime shr 32)); {This should work out nicely, as there were approx. 250 ms between the calls and the result will be a percentage between 0 and 100} Result:=((TotalTime2-TotalTime1)/cWaitTime)/100; CloseHandle(h); end; Ich habe nun 2 Programme geschrieben. Ein Consolenprogramm und eine VCL Formularanwendung. In beiden Programmen rufe ich die Funktionen so auf
Delphi-Quellcode:
Wenn ich das VCL Formular Programm nun auf einem Windows Server 2008 R2 starte wird mir der Memoryverbrauch angezeicgt. Wenn ich hingegen das Consolenprogramm starte wird mir "fehler" an der Console ausgegeben
ww := GetProcessMemorySize(prozess_name, dmem)
oder (ich habe beide probiert) dmem := ShowMemoryUsage(GetPIDByProgramName(prozess_name)); kommt hier her
Delphi-Quellcode:
Ich habe die Console auch mal als Administrator ausgeführt. Es kommt auch "fehler" raus.
l_nWndHandle := FindWindow(nil, PChar(sProcessName));
if l_nWndHandle = 0 then begin writeln('fehler'); Result := False; Exit; end; Auf einem Windows Server 2003 funktionieren beide Programme CPU Nutzung kommt auf allen Servern und auch bei beiden Programmen raus ?!?!? Verstehe ich nicht. Kann mir einer helfen Viele Grüße Andreas |
AW: CPU und Memory Nutzung eines Prozesses
Ich glaube das ich ein Berechtigungsproblem. Scheinbar dürfen die Funktionen "GetProcessMemorySize" und "ShowMemoryUsage" den "OpenProcess" nicht aufrufen die Funktion GetCpuUsage aber schon.
Ich bin jetzt nicht genug Windows Administrator um das nachvollziehen zu können. Kann man irgendwie das Kommando mit einem Benutzer/Kennwort aufrufen??? Wobei die RDP Sitzung habe ich mit einem Administrator Account aufgemacht und wie Beschrieben die Console auch als Administrator gestartet. Oder hat einer eine andere Lösung? |
AW: CPU und Memory Nutzung eines Prozesses
Hachja, Meldungen wie "Es ist ein Fehler aufgetreten" sind immer wieder schön zu sehen :roll:. Wie wär's mit GetLastError, wenn eine Funktion wie FindWindow fehlschlägt? Oder gar gleich sowas:
Delphi-Quellcode:
damit man etwas konkretere Angaben bekommt.
WriteLn(SysErrorMessage(GetLastError));
MfG Dalai |
AW: CPU und Memory Nutzung eines Prozesses
Würdest du die Rückgabewerte der aufgerufenen WinAPIs auswerten, dann wüsstest du, warum die nicht so wollen, wie so sollen.
|
AW: CPU und Memory Nutzung eines Prozesses
OK, habe WriteLn(SysErrorMessage(GetLastError)); eingebaut
GetProcessMemorySize gibt "Der an einen Systemaufruf übergebene Datenbereich ist zu klein" zurück. Hiermit kann ich nichts anfangen ShowMemoryUsage gibt "Zugriff verweigert" zurück. Das hatte ich ja vermutet. Nun die Frage wie kann ich Aufruf berechtigen?? ok " Rückgabewerte der aufgerufenen WinAPIs auswerten" Wie mach ich das? |
AW: CPU und Memory Nutzung eines Prozesses
Zitat:
Ups, hab die Zuweisung der Größe übersehen, sorry. Die Meldung bedeutet, dass der Puffer, den du an eine Funktion übergeben hast, zu klein ist, um die Daten vollständig zurückzugeben. Du solltest ermitteln, welche API-Funktion genau diesen Fehler wirfst, und dann den Puffer vergrößern. Zitat:
Zitat:
MfG Dalai |
AW: CPU und Memory Nutzung eines Prozesses
Zitat:
![]() ![]() Die dynamische Speicherverwaltung (getMem/freeMem) ist an der Stelle auch völlig überflüssig, PROCESS_MEMORY_COUNTERS passt locker auf den Stack. Auf jeden Fall gibt GetProcessMemory genau dann 0 zurück, wenn ein Fehler aufgetreten ist. Dann kannst du zum Beispiel eine ![]() Analog bei allen anderen Systemaufrufen. |
AW: CPU und Memory Nutzung eines Prozesses
der Fehler in ShowMemoryUsage kommt hier
Delphi-Quellcode:
das "SysErrorMessage(GetLastError));" bringt "Zugriff verweigert" in der Funktion GetCpuUsage benutze ich "h:=OpenProcess(PROCESS_QUERY_INFORMATION,false,PI D);" und ich bekomme keinen Fehler.
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessId);
begin if ( hProcess = 0 ) then begin WriteLn(SysErrorMessage(GetLastError)); writeln('fehler'); Exit; end;
Delphi-Quellcode:
der Fehler in "GetProcessMemorySize" kommt hier
function GetCpuUsage(PID:cardinal):single;
const cWaitTime=750; var h : Cardinal; mCreationTime,mExitTime,mKernelTime, mUserTime:_FILETIME; TotalTime1,TotalTime2:int64; begin {We need to get a handle of the process with PROCESS_QUERY_INFORMATION privileges.} h:=OpenProcess(PROCESS_QUERY_INFORMATION,false,PID); {We can use the GetProcessTimes() function to get the amount of time the process has spent in kernel mode and user mode.} GetProcessTimes(h,mCreationTime,mExitTime,mKernelTime,mUserTime); TotalTime1:=int64(mKernelTime.dwLowDateTime or (mKernelTime.dwHighDateTime shr 32)) + int64(mUserTime.dwLowDateTime or (mUserTime.dwHighDateTime shr 32)); {Wait a little} Sleep(cWaitTime); GetProcessTimes(h,mCreationTime,mExitTime,mKernelTime,mUserTime); TotalTime2:=int64(mKernelTime.dwLowDateTime or (mKernelTime.dwHighDateTime shr 32)) + int64(mUserTime.dwLowDateTime or (mUserTime.dwHighDateTime shr 32)); {This should work out nicely, as there were approx. 250 ms between the calls and the result will be a percentage between 0 and 100} Result:=((TotalTime2-TotalTime1)/cWaitTime)/100; CloseHandle(h); end;
Delphi-Quellcode:
l_nWndHandle := FindWindow(nil, PChar(sProcessName));
if l_nWndHandle = 0 then begin WriteLn(SysErrorMessage(GetLastError)); writeln('fehler'); Result := False; Exit; end; |
AW: CPU und Memory Nutzung eines Prozesses
Zitat:
dieser gibt 0 zutück ich denke schon das das in dem selben Berechtigungskonzept passiert. Ist alles ein Programm in einer EXE und das läuft als Consolenprogramm. Die Console ist als Admin ausgeführt. |
AW: CPU und Memory Nutzung eines Prozesses
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:55 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