AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

CPU und Memory Nutzung eines Prozesses

Ein Thema von af99 · begonnen am 20. Mai 2015 · letzter Beitrag vom 21. Mai 2015
Antwort Antwort
Seite 1 von 2  1 2      
af99

Registriert seit: 22. Apr 2004
84 Beiträge
 
Delphi XE5 Ultimate
 
#1

CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 13:03
Delphi-Version: XE5
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:
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;
Für die Ermittlung des Memory Verbrauchs habe ich 2 Funktionen die ich beide versucht habe.
Ich habe nun 2 Programme geschrieben. Ein Consolenprogramm und eine VCL Formularanwendung.

In beiden Programmen rufe ich die Funktionen so auf
Delphi-Quellcode:
ww := GetProcessMemorySize(prozess_name, dmem)

oder (ich habe beide probiert)

dmem := ShowMemoryUsage(GetPIDByProgramName(prozess_name));
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
kommt hier her
Delphi-Quellcode:
  l_nWndHandle := FindWindow(nil, PChar(sProcessName));
  if l_nWndHandle = 0 then
  begin
    writeln('fehler');
    Result := False;
    Exit;
  end;
Ich habe die Console auch mal als Administrator ausgeführt. Es kommt auch "fehler" raus.
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
  Mit Zitat antworten Zitat
af99

Registriert seit: 22. Apr 2004
84 Beiträge
 
Delphi XE5 Ultimate
 
#2

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 13:47
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?
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.682 Beiträge
 
Delphi 5 Professional
 
#3

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 13:55
Hachja, Meldungen wie "Es ist ein Fehler aufgetreten" sind immer wieder schön zu sehen . Wie wär's mit GetLastError, wenn eine Funktion wie FindWindow fehlschlägt? Oder gar gleich sowas: WriteLn(SysErrorMessage(GetLastError)); damit man etwas konkretere Angaben bekommt.

MfG Dalai
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 13:56
Würdest du die Rückgabewerte der aufgerufenen WinAPIs auswerten, dann wüsstest du, warum die nicht so wollen, wie so sollen.
$2B or not $2B
  Mit Zitat antworten Zitat
af99

Registriert seit: 22. Apr 2004
84 Beiträge
 
Delphi XE5 Ultimate
 
#5

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 14:05
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?
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.682 Beiträge
 
Delphi 5 Professional
 
#6

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 14:29
GetProcessMemorySize gibt "Der an einen Systemaufruf übergebene Datenbereich ist zu klein" zurück. Hiermit kann ich nichts anfangen
Aber ich bin mir sicher, dass dein Compiler dich warnt, dass die Variable l_pPMCSize wahrscheinlich nicht initialisiert wurde in der genannten Funktion. Also solltest du das beheben, und dann mit einer passenden Größe Speicher anfordern. Ohne jetzt genauer geschaut zu haben, könnten noch weitere ähnliche Warnungen vorhanden sein.

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:
ShowMemoryUsage gibt "Zugriff verweigert" zurück. Das hatte ich ja vermutet. Nun die Frage wie kann ich Aufruf berechtigen??
Welchen Prozess versuchst du denn zu öffnen? Einen, der mit demselben Berechtigugnskontext läuft wie dein Programm? Oder den eines anderen Nutzers? Für letzteres braucht man Adminrechte.

Zitat:
ok " Rückgabewerte der aufgerufenen WinAPIs auswerten" Wie mach ich das?
Konsequent die Funktionsrückgaben auswerten. Ja, klingt doof, aber was gibt denn eine API-Funktion meist zurück? Einen Rückgabewert. Und den solltest du auswerten und bei Fehlschlag eben GetLastError rufen, sofern das im MSDN so angegeben ist für die jeweilige Funktion. Bei einigen Funktionen machst du das ja, aber eben nicht bei allen.

MfG Dalai

Geändert von Dalai (20. Mai 2015 um 14:32 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#7

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 14:41
GetProcessMemorySize gibt "Der an einen Systemaufruf übergebene Datenbereich ist zu klein" zurück.
...
ok " Rückgabewerte der aufgerufenen WinAPIs auswerten" Wie mach ich das?
Guck dir mal den GetProcessMemory-Aufruf an, der setzt vermutlich die oben genannte Fehlermeldung. Kompilierst du zufällig für 64bit? PROCESS_MEMORY_COUNTERS könnte dann eine andere Größe haben (wegen SIZE_T)
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 Exception mit dem Errorcode werfen.
Analog bei allen anderen Systemaufrufen.
  Mit Zitat antworten Zitat
af99

Registriert seit: 22. Apr 2004
84 Beiträge
 
Delphi XE5 Ultimate
 
#8

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 15:10
der Fehler in ShowMemoryUsage kommt hier
Delphi-Quellcode:
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessId);
     begin
       if ( hProcess = 0 ) then
       begin
         WriteLn(SysErrorMessage(GetLastError));
         writeln('fehler');
         Exit;
       end;
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.
Delphi-Quellcode:
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;
der Fehler in "GetProcessMemorySize" kommt hier
Delphi-Quellcode:
  l_nWndHandle := FindWindow(nil, PChar(sProcessName));
  if l_nWndHandle = 0 then
  begin
    WriteLn(SysErrorMessage(GetLastError));
    writeln('fehler');
    Result := False;
    Exit;
  end;
  Mit Zitat antworten Zitat
af99

Registriert seit: 22. Apr 2004
84 Beiträge
 
Delphi XE5 Ultimate
 
#9

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 15:15
Zitat:
Welchen Prozess versuchst du denn zu öffnen? Einen, der mit demselben Berechtigugnskontext läuft wie dein Programm? Oder den eines anderen Nutzers? Für letzteres braucht man Adminrechte.
diesen l_nWndHandle := FindWindow(nil, PChar(sProcessName));
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.
  Mit Zitat antworten Zitat
af99

Registriert seit: 22. Apr 2004
84 Beiträge
 
Delphi XE5 Ultimate
 
#10

AW: CPU und Memory Nutzung eines Prozesses

  Alt 20. Mai 2015, 15:17
Zitat:
Kompilierst du zufällig für 64bit?
nein als 32 BIT
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:42 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz