![]() |
EnumProcesses
Ich versuche gerade eine Prozessliste mit EnumProcesses zu bekommen. Ich habe da schon eine funktionierden Version auf meiner HP, wollte es aber besser machen:
Delphi-Quellcode:
Im PSDK steht:
function GetProcessList(out ProcessList: TProcessList): DWORD;
function GetOSVersionInfo(var Info: TOSVersionInfo): Boolean; begin FillChar(Info, SizeOf(TOSVersionInfo), 0); Info.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); Result := GetVersionEx(TOSVersionInfo(Addr(Info)^)); if (not Result) then begin FillChar(Info, SizeOf(TOSVersionInfo), 0); Info.dwOSVersionInfoSize := SizeOf(TOSVersionInfo); Result := GetVersionEx(TOSVersionInfo(Addr(Info)^)); if (not Result) then Info.dwOSVersionInfoSize := 0; end; end; var OSInfo : TOSVersionInfo; PidProcesses : PDWORD; PidWork : PDWORD; BufferSize : Cardinal; cbNeeded : Cardinal; cntProcesses : Cardinal; i : Cardinal; begin result := 0; // What OS are we running on? if GetOSVersionInfo(OSInfo) then begin if (OSInfo.dwPlatformId = VER_PLATFORM_WIN32_NT) and (OSInfo.dwMajorVersion = 5) then // WinNT and higher begin cbNeeded := 0; BufferSize := 0; // how much memory do we need if EnumProcesses(nil, BufferSize, cbNeeded) then begin cntProcesses := cbNeeded div sizeof(DWORD); GetMem(PidProcesses, cntProcesses); if EnumProcesses(PidProcesses, cntProcesses, cbNeeded) then begin PidWork := PidProcesses; setlength(ProcessList, cntProcesses); for i := 0 to cntProcesses - 1 do begin ProcessList[i] := PidWork^; Inc(PidWork, sizeof(PDWORD)); end; end; FreeMem(PidProcesses, cntProcesses); end; end // Win 9x and higher except WinNT else begin end; end; end; Zitat:
Mache ich es so:
Delphi-Quellcode:
Dann geht es. Nur finde ich es etwas blöd unnötig Speicher zu reservieren.
procedure TForm1.Button1Click(Sender: TObject);
var pdwResult : PDWORD; // für den Buffer pdwWork : PDWORD; // um dem Buffer verarbeiten zu können dwCountIn : DWORD; // Grösse des Buffers in Byte dwCountOut : DWORD; // Zurückgelieferte Anzahl Byte i : integer; begin dwCountOut := 0; // Sicherheitshalber initialisieren, muss nicht sein dwCountIn := 1024; // Willkürlich gewählt, genügt für 256 Prozesse pdwResult := AllocMem(dwCountIn); try if not EnumProcesses(pdwResult,dwCountIn,dwCountOut) then begin RaiselastOSError(); end else begin pdwWork := pdwResult; // zur Verarbeitung übergeben, damit FreeMem funktioniert for i := 1 to (dwCountOut shr 2) do begin // shr 2 = / 4, da 4 Byte je DWORD // Prozess Id ausgeben //ShowMessage('ProzessId# '+IntToStr(i)+': '+IntToStr(pdwWork^)); ListBox1.Items.Add(GetProcessName(pdwWork^)); // auf nächste addressieren (inc erhöht automatisch um 4, da es ein typisierter Pointer ist inc(pdwWork); end; end; finally FreeMem(pdwResult,dwCountIn); end; end; |
Re: EnumProcesses
Es steht aber auch so in der Hilfe, das du keine Möglichkeit hast zu ermitteln wieviel Speicher du wirklich brauchst. Sondern das du ausreichend Speicher reservieren sollst. Von daher finde ich das C Beispiel in dem Platform SDK ganz gut.
|
Re: EnumProcesses
Gut, wenn sie es nicht anders wollen. :roll:
|
Re: EnumProcesses
OK. So sieht es jetzt aus:
![]() |
Re: EnumProcesses
Zwei Fehler:
1. Der Versionscheck funktioniert mit NT 4 da es = 4 anstatt >= 4 testet 2. OpenProcess() zu verwenden um den Dateinamen des Prozesses zu verwenden ist nicht zuverlaessig weil man ggf. nicht die noetigen Rechte hat (sieht man an den "unbekannt" eintraegen in der liste Ich werde ein Beispiel wie M$ diese Funktion implementiert hat mit Hilfe der native API hier posten, denn die liefert eigentlich schon genug Informationen, inkl. der Dateinamen fuer alle Prozesse. Die NAPI funktionen sind zwar undokumentiert von M$, aber sie sind in einigen Buechern gut dokumentiert und haben sich ausserdem seit NT 4 nicht geaendert, unwahrscheinlich also dass sie jemals geaendert werden. Ausserdem gibt es eine Reihe von Programmen wie der TaskManager die auf diese Methode zurueckgreifen. [edit: ich seh gerade dass das neueste PSDK diese funktionen doch dokumentiert hat] |
Re: EnumProcesses
Zitat:
Zitat:
Zitat:
Zitat:
|
Re: EnumProcesses
Zitat:
Zitat:
|
Re: EnumProcesses
Zitat:
Die Wahrscheinlich dass diese Funktionen geaendert werden geht gegen null, erstens wurden sie endlich von M$ dokumentiert und zweitens benoetigen viele Programme, insbesondere Virenscanner und Firewalls diese Funktion... gebt mir noch ein paar Miuten... |
Re: EnumProcesses
Wie heißen denn die Funktionen?
|
Re: EnumProcesses
Zitat:
Code:
NTSTATUS NtQueryInformationProcess(
HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength ); |
Re: EnumProcesses
nein, das ganze funktioniert mit NtQuerySystemInformation().
Ich hab mal die Funktion EnumProcesses in Delphi nachgebaut, so oder sehr Aehnlich duerfte sie Microsoft implementiert haben:
Delphi-Quellcode:
wie man erkennen kann, enthaelt die SYSTEM_PROCESS_INFORMATION structure ein Feld namens ImageName, welches ein unicode string ist, den den Prozessnamen (also den Dateinamen des Images des Prozesses) enthaelt. Das Feld Buffer in diesem Unicode string zeigt einfach auf das Ende der structure die gerade enumeriert wurde, deshalb gibt es auch ein Feld NextEntryOffset um den Beginn der naechsten structure finden zu koennen.
const
SystemProcessInformation = 5; STATUS_INFO_LENGTH_MISMATCH = Integer($C0000004); type UNICODE_STRING = record Length: Word; MaximumLength: Word; Buffer: PWideChar; end; PUNICODE_STRING = ^UNICODE_STRING; TUNICODE_STRING = UNICODE_STRING; _SYSTEM_PROCESS_INFORMATION = record NextEntryOffset: ULONG; NumberOfThreads: ULONG; SpareLi1, SpareLi2, SpareLi3: TLargeInteger; CreateTime, UserTime, KernelTime: TLargeInteger; ImageName: UNICODE_STRING; BasePriority: ULONG; UniqueProcessId: THandle; InheritedFromUniqueProcessId: THandle; HandleCount: ULONG; SessionId: ULONG; SpareUl3: ULONG; PeekVirtualSize: ULONG; VirtualSize: ULONG; PageFaultCount: ULONG; PeakWorkingSetSize: ULONG; WorkingSetSize: ULONG; QuotaPeakPagedPoolUsage: ULONG; QuotaPagedPoolUsage: ULONG; QuotaPeakNonPagedPoolUsage: ULONG; QuotaNonPagedPoolUsage: ULONG; PagefileUsage: ULONG; PeakPagefileUsage: ULONG; PrivatePageCount: ULONG; end; TSYSTEM_PROCESS_INFORMATION = _SYSTEM_PROCESS_INFORMATION; PSYSTEM_PROCESS_INFORMATION = ^TSYSTEM_PROCESS_INFORMATION; function NtQuerySystemInformation(SystemInformationClass: Cardinal; SystemInformation: Pointer; Length: ULONG; ResultLength: PULONG): Integer; stdcall; external 'ntdll.dll'; function RtlNtStatusToDosError(StatusCode: Integer): DWORD; stdcall; external 'ntdll.dll'; function EnumProcesses(pProcessIds: PDWORD; cb: DWORD; var pBytesReturned: DWORD): BOOL; stdcall; const BUF_SIZE = $10000; var ProcListBuffer: PChar; ProcessInfo: PSYSTEM_PROCESS_INFORMATION; ProcOffset: ULONG; BufSize: Cardinal; Status: Integer; begin Result := false; // capture the process list BufSize := BUF_SIZE; repeat GetMem(ProcListBuffer, BufSize); if ProcListBuffer = nil then begin SetLastError(ERROR_NOT_ENOUGH_MEMORY); Exit; end; Status := NtQuerySystemInformation(SystemProcessInformation, ProcListBuffer, BufSize, nil); if Status = STATUS_INFO_LENGTH_MISMATCH then begin // Buffer was too small, increase the buffer size and try again FreeMem(ProcListBuffer); Inc(BufSize, BUF_SIZE); end else if Status < 0 then begin // Another error occured FreeMem(ProcListBuffer); SetLastError(RtlNtStatusToDosError(Status)); Exit; end; until Status >= 0; pBytesReturned := 0; // we got the entire process list now, extract all PIDs ProcOffset := 0; ProcessInfo := PSYSTEM_PROCESS_INFORMATION(ProcListBuffer); while cb >= SizeOf(DWORD) do begin ProcessInfo := PSYSTEM_PROCESS_INFORMATION(Cardinal(ProcessInfo) + ProcOffset); pProcessIds^ := DWORD(ProcessInfo^.UniqueProcessId); ProcOffset := ProcessInfo^.NextEntryOffset; Inc(pProcessIds); Dec(cb, SizeOf(DWORD)); Inc(pBytesReturned, SizeOf(WORD)); if ProcOffset = 0 then begin Result := true; Break; end; end; FreeMem(ProcListBuffer); end; Der Task Manager, die PSAPI implementierung von EnumProcesses() und auch die Toolhelp32 API (welche ich fast komplett fuer ReactOS ![]() Hoffe das bringt etwas mehr Licht in die duesteren APIs von Windows ;) |
Re: EnumProcesses
Hast du mal eben eine Demo dazu?
|
Re: EnumProcesses
Zitat:
|
Re: EnumProcesses
Wie stellst du dir jetzt vor kommt man an den Modulnamen dran?
|
Re: EnumProcesses
geb mir ein paar minuten ich bau mal eben ein beispiel programm
|
Re: EnumProcesses
Äh, ich dachte das wäre schonm da. Irgendiwe musst du die Funktion ja entwickelt haben. :gruebel:
|
Re: EnumProcesses
Liste der Anhänge anzeigen (Anzahl: 1)
Das was ich entwickelt hatte ist nur dazu da um zu sehen wie EnumProcesses implementiert ist, denn damit kann man sehr sehr viel anfangen:
hier das Beispielprogramm das darauf basiert als Anhang |
Re: EnumProcesses
nur des Feedbacks wegen, verstanden wie das funktioniert? ;)
|
Re: EnumProcesses
Ich bin noch nicht dazu gekommen, mir das anzugucken. Ich hatte gerade am Sonntag noch Zeit mir das mal runterzuladen und schnell mal zu starten und bin gerade erst nach hause gekommen. ;)
|
Re: EnumProcesses
Zitat:
|
Re: EnumProcesses
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
eine kurze Frage zum Programm! Wie kann das sein? Ich ändere den Dateinamen in Project.exe und das was mir angezeigt wird in der Liste ist "Project.exee" was läuft den an der Stelle falsch? Darf ich den Programmnamen nicht ändern (compilerproblem?)? Wird dieser dann falch angezeigt? Wer weiß da Rat??? Beste Grüße Mitchl |
Re: EnumProcesses
Hallo,
gibt es auch eine Möglichkeit Speicherbedarf und CPU-Auslastung der Prozesse zu ermitteln? |
Re: EnumProcesses
Zitat:
|
Re: EnumProcesses
Zitat:
Vielen Dank, Tobi |
Re: EnumProcesses
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:49 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