![]() |
Startparameter fremder Anwendung auslesen
Hallo Gemeinde,
ich habe gerade ein kleines Problem beim Auslesen der Startparameter einer "fremden" Anwendung. Unter Windows XP funktioniert alles wunderbar, ab Vista aber geht nichts mehr. Erstmal ein Schnipsel Code:
Delphi-Quellcode:
In der Variablen "Parameter" steht unter XP der bzw. die Parameter, welche mit dem Programmstart übergeben wurden. Gebe ich mir diese Variable mit ShowMessage zum Beispiel aus, ist der Wert unter Vista leer. Ich gehe also quasi alle Prozesse durch uns suche die Prozesse, die denselben Namen habe wie meine EXE. Von diesen möchte ich dann die Parameter auslesen.
Snap := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
try ProcessE.dwSize := SizeOf(ProcessE); if Process32First(Snap, ProcessE) then begin repeat if ExtractFilePath(ParamStr(0)) + ProcessE.szExeFile = Application.ExeName then begin Parameter := GetStartParameter(ProcessE.th32ProcessID); Frage ist jetzt, wieso das unter Vista nicht funkioniert bzw. was ich ändern muss. Vielen Dank fürs Lesen! Gruß, Michael |
Re: Startparameter fremder Anwendung auslesen
Dazu solltest Du aber den Source von GetStartParameter posten ;).
|
Re: Startparameter fremder Anwendung auslesen
Hallo,
ja, da hast du allerdings Recht :wall: Vielleicht sollte man nicht immer alles gleichzeitig machen...
Delphi-Quellcode:
So, dass ist die Funktion.
function GetStartParameter(ProcessID: DWORD): String;
var MBI : TMemoryBasicInformation; Buffer,PosCmdLine : Pointer; SystemInfo : TSystemInfo; Size : DWORD; CmdLine : WideString; LengthCmdLine : Word; ProcessHandle : THandle; begin Result := ''; FillChar(SystemInfo, SizeOf(TSystemInfo), 0); GetSystemInfo(SystemInfo); GetMem(Buffer, SystemInfo.dwPageSize); Size := SizeOf(TMemoryBasicInformation); FillChar(MBI, Size, 0); ProcessHandle := OpenProcess(PROCESS_VM_READ or PROCESS_QUERY_INFORMATION, False, ProcessId); if VirtualQueryEx(ProcessHandle, Pointer($20000), MBI, Size) = Size then if ReadProcessMemory(ProcessHandle, MBI.BaseAddress, Buffer, SystemInfo.dwPageSize, DWORD(nil^)) then begin LengthCmdLine := PWord(Longint(Buffer) + $42)^; if LengthCmdLine < 520 then begin SetLength(CmdLine,LengthCmdLine); PosCmdLine := Pointer(PLongint(Longint(Buffer) + $44)^); if ReadProcessMemory(ProcessHandle, PosCmdLine, PWideChar(CmdLine), LengthCmdLine, DWORD(nil^)) then Result := Copy(CmdLine, 1, Pos(#0,CmdLine) - 1); end; end; CloseHandle(Processhandle); FreeMem(Buffer); end; Danke! Gruß, Michael |
Re: Startparameter fremder Anwendung auslesen
Was Du in der Funktion machst ist an fixen Offsets die Parameter zu lesen. Die Offsets mögen für Windows XP konstant sein, können sich in späteren Windows Versionen aber ändern.
Der korrekte Weg wäre die Adresse des PEB innerhalb des fremden Prozesses zu ermitteln, den PEB dann auszulesen um den Pointer auf die ProcessParameters Datenstruktur zu erhalten, selbige dann wiederum zu lesen um dann letztlich an die Command Line zu kommen. Die Methode funktioniert dann auch für alle Windows Versionen, solange sich die Datenstrukturen nicht grundlegend ändern. Da Microsoft aber meist neue Parameter "hinten dranhängt", solltest Du damit keine Probleme haben. Eine Implementation des Ganzen gibts hier sogar im Board: ![]() PS: Gewöhn Dir an statt "Magic Values" Konstanten zu benutzen. Niemand weiß sonst was $200000 dort soll oder $44. |
Re: Startparameter fremder Anwendung auslesen
'ne andere Möglichkeit wäre noch:
- eine DLL oder Code in den gewünschten Prozess injizieren - und dort GetCommandLine aufrufen |
Re: Startparameter fremder Anwendung auslesen
Also ich mache das etwa so (keine injection, dafür aber debugging-Rechte) ...
Delphi-Quellcode:
Referenz:
function GetProcessCommandLine(pID: Cardinal):string;
var hProcess, hHeap: THandle; dwsize, dwSizeNeeded, dwBytesRead: DWORD; dwStatus: LONG; pbi : smPPROCESS_BASIC_INFORMATION; spi : smPROCESSINFO; peb : smPEB; bpp: smRTL_USER_PROCESS_PARAMETERS; pWideStrBuf: PWideChar; begin if not EnableTokenPrivilege(SE_DEBUG_NAME) then begin // writeln('Debug privileges not available for current user.'); end; result := ''; hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, // PROCESS_ALL_ACCESS,// false, PID); if hProcess = 0 then begin // writeln('Could not open process #',pID,' with desired privileges. Error ',GetLastError); exit; end; // else writeln('access granted.'); if IsNTDLLLibraryLoaded then begin hHeap := GetProcessHeap; if hHeap <> 0 then begin dwSize := sizeof(smPROCESS_BASIC_INFORMATION); pbi := HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize); if assigned(pbi) then begin dwStatus := NtQueryInformationProcess(hProcess, ProcessBasicInformation, Pointer(pbi), dwSize, @dwSizeNeeded); if dwStatus >= 0 then begin spi.dwPID := DWORD (pbi^.UniqueProcessId); spi.dwParentPID := DWORD (pbi^.InheritedFromUniqueProcessId); spi.dwBasePriority := LONG (pbi^.BasePriority); spi.dwExitStatus := NTSTATUS (pbi^.ExitStatus); spi.dwPEBBaseAddress := DWORD (pbi^.PebBaseAddress); spi.dwAffinityMask := DWORD (pbi^.AffinityMask); if 0 <> spi.dwPEBBaseAddress then begin if ReadProcessMemory ( hProcess, Pointer(spi.dwPEBBaseAddress), @peb, sizeof(peb), dwBytesRead) then begin spi.dwSessionID := DWORD (peb.SessionId); spi.cBeingDebugged := BYTE (peb.BeingDebugged); try if assigned(peb.ProcessParameters) then begin ReadProcessMemory( hProcess,Pointer(peb.ProcessParameters),@bpp,sizeof(bpp),dwBytesRead); if bpp.CommandLine.Length > 0 then begin pWideStrBuf := HeapAlloc(hHeap,HEAP_ZERO_MEMORY,bpp.CommandLine.Length*sizeof(WideChar)); ReadProcessMemory( hProcess, bpp.CommandLine.Buffer, pWideStrBuf, bpp.CommandLine.Length*sizeof(WideChar), dwBytesRead); result := WideCharToString(pWideStrBuf); HeapFree(hHeap,0,pWideStrBuf); end; end; except else result := ' - '; end; end; // else writeln('ReadMemory Failed.'); end; // else writeln('PEB Base Address is NULL.'); end; // else writeln('NtQueryInformationProcess Failed.'); end; // else writeln('HeapAlloc Failed.'); if hHeap <> 0 then windows.HeapFree(hHeap,0,pbi); // 0 : Do not specify this value when accessing the process heap. The system may create additional threads within the application's process, such as a CTRL+C handler, that simultaneously access the process heap. Otherwise, use HEAP_NO_SERIALIZE = 1 end; end; CloseHandle(hProcess); end; ![]() |
Re: Startparameter fremder Anwendung auslesen
Hallo,
ringli hatte in einem verlinkten Thread eine Demo verlinkt. Mit dieser konnte ich das Problem jetzt erst einmal lösen. @Fridolin Walther: Deine Antwort liest sich sehr gut, umsetzen konnte ich sie leider nicht. In deinem Source sind z.B. die Units JwaWinBase und JwaNative erwähnt. Wo bekomme ich die her? Vielen Dank an alle für die Tipps!! Gruß, Michael |
Re: Startparameter fremder Anwendung auslesen
|
Re: Startparameter fremder Anwendung auslesen
Du brauchst keine Debuggingrechte, wenn du nur deine eigenen Prozesse öffnen willst. Lass das also weg.
|
Re: Startparameter fremder Anwendung auslesen
Hallo,
@Fridolin Walthe: Danke für den Hinweis! Bei Gelegenheit werde ich mir das sicherlich noch mal im Detail ansehen. @Dezipaitor: Ja, es handelt sich hierbei um die eigene Anwendung. Funktionieren tut es auch, von daher ist dieser Punkt für mich erledigt. Danke noch einmal an Alle! Gruß, Michael |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:14 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