Autor Beitrag
Karlson
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 2088



BeitragVerfasst: Do 28.04.05 23:37 
Prozessliste unter Windows NT

Funktion Suche im MSDN ENUMPROCESSES

EnumProcesses setzt sich aus den Worten "enumerate" und "processes" zusammen und bedeutet soviel wie: Prozess-Nummerierung oder Prozess-Auflistung.

Laut MSDN macht die Funktion folgendes The EnumProcesses function retrieves the process identifier for each process object in the system..

Aufgebaut ist sie so:

ausblenden Quelltext
1:
2:
3:
4:
5:
BOOL EnumProcesses(
  DWORD* pProcessIds,
  DWORD cb,
  DWORD* pBytesReturned
);


Es ist also eine Funktion mit einem Boolschen Rückgabewert (unter Delphi nennt sich das auch Boolean). Die Funktion gibt NonZero bzw. True zurück wenn alles geklappt hat. Wenn nicht erhalten wir 0 bzw. False.
Sollte die Funktion schiefgegangen sein, können wir mithilfe der Suche im MSDN RAISELASTOSERROR-Procedure den Fehler anzeigen lassen.

Parameter


  1. pProcessIds | Typ DWORD | Hierbei handelt es sich um einen Out-Parameter. Wir geben ihn sozusagen leer hinein und bekommen ihn mit den Process Identifiers gefüllt wieder zurück.

  2. cb | Typ DWORD | Die Grösse des Pointerarrays (Parameter 1). Braucht uns nicht weiter zu intressieren, siehe weiter unten.

  3. pBytesReturned | Typ DWORD | Ebenfalls ein Out Parameter. Hier drin wird gespeichert wieviel Bytes vom Parameter 1 - Array beschrieben wurden.


Unit

Die Funktion befindet sich in der Unit PsApi. Also diese Unit unter Uses einbinden.


Anwendung

Bevor wir die Funktion aufrufen wissen wir nicht wieviele Prozesse momentan laufen, ergo wissen wir auch nicht wie gross wir das Array wählen sollen. Da wir die Grösse des Arrays erst beim Beschreiben kennen fällt auch ein dynamisches Array flach.

Laut MSDN It is a good idea to use a large array, und zwar aus dem obengenannten Grund.

Wir rechnen hier jetzt allerdings mal damit dass es schwer sein dürfte 100 Prozesse gleichzeitig laufen zu haben. Sollte der Platz denoch nicht ausreichen können wir innerhalb der Funktion reagieren.

Der Quellcode:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
function ProcessList:TStringList;
var PrIDs : Array [0..100of DWORD;
      bia : DWORD;
  PrCount : Integer;
  ProzessHandle : HWND;
  Modulhandle : HWND;
  i : Integer;
  PrName : Array [0..255of Char;
begin
Result:=TStringList.Create;
if EnumProcesses(@PrIDs, SizeOf(PrIDs), bia) then
 if bia < sizeof(PrIDs) then
  begin
   PrCount:=Bia div SizeOf(DWORD);
   for i:=0 to PrCount do
    begin
     ProzessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or
                                  PROCESS_VM_READ, false, PrIDS[i]);
     if ProzessHandle<>0 then
      begin
       EnumProcessModules(ProzessHandle, @ModulHandle, SizeOf(modulhandle), bia);
       GetModuleFilenameEx(Prozesshandle, ModulHandle, PrName, SizeOf(PrName));
       Result.add(PrName);
       CloseHandle(ProzessHandle);
      end;
    end;
  end else messageDlg('PrID-Array zu klein', mtError, [mbOk], 0)//if bia < sizeof...
 else RaiseLastOSError(); //if enumprocesses...
end;


Die ganze Prozedur läuft eigentlich recht einfach ab: Mit EnumProcesses lädt man sich die ProcessIDs aller laufenden Prozesse in das Array PrIDs. Dann geht man Prozess-ID für Prozess-ID durch, und erhält mit OpenProcess das Prozesshandle. Wenn man das Prozesshandle hat ruft man GetModuleFilenameEx auf in dessen Out-Parameter PrName dann der Exe-Name des laufenden Processes gespeichert wird.

Die Funktion Processlist gibt eine mit den Prozessen gefüllte Stringlist zurück. Dabei wird der komplette Pfad geliefert. Wer eine Darstellung wie Windows Taskmanager möchte, kann mit Suche in: Delphi-Forum, Delphi-Library EXTRACTFILENAME die Pfadangabe aus dem String löschen.

Wer die Funktion übrigens mit eingeschränkten Rechten ausführt, bekommt nur die Prozesse zu sehen die unter dem entsprechendem Konto laufen. Besonders bei Vista macht das mitunter Probleme: Wer unter Vista ein vollständige Prozessliste bekommen will, muss das Programm in dem sich die Funktion befindet, mit Administratorrechten starten. Andernfalls umfasst die Liste nicht alle Prozesse.

Aufrufen kann man die Funktion z.B. so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.Button1Click(Sender: TObject);
var
  tmpList : TStringList;
begin
  tmpList := ProcessList;
  try
    listbox1.items.assign(tmpList);
  finally
    tmpList.Free;
  end;
end;


Den Api-Befehl EnumProcesses gibt es nur auf NT-Maschinen, also Windows 2000 / XP / Vista. Wer Windows 9x benutzt muss auf Suche im MSDN CREATETOOLHELP32SNAPSHOT ausweichen.