Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Startparameter fremder Anwendung auslesen (https://www.delphipraxis.net/148405-startparameter-fremder-anwendung-auslesen.html)

mw19 1. Mär 2010 14:21


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:
  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);
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.

Frage ist jetzt, wieso das unter Vista nicht funkioniert bzw. was ich ändern muss.

Vielen Dank fürs Lesen!

Gruß,
Michael

Fridolin Walther 1. Mär 2010 14:27

Re: Startparameter fremder Anwendung auslesen
 
Dazu solltest Du aber den Source von GetStartParameter posten ;).

mw19 1. Mär 2010 14:31

Re: Startparameter fremder Anwendung auslesen
 
Hallo,

ja, da hast du allerdings Recht :wall:
Vielleicht sollte man nicht immer alles gleichzeitig machen...

Delphi-Quellcode:
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;
So, dass ist die Funktion.

Danke!

Gruß,
Michael

Fridolin Walther 1. Mär 2010 15:01

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:
http://www.delphipraxis.net/internal...=873389#873389

PS: Gewöhn Dir an statt "Magic Values" Konstanten zu benutzen. Niemand weiß sonst was $200000 dort soll oder $44.

himitsu 1. Mär 2010 15:17

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

helgew 1. Mär 2010 15:33

Re: Startparameter fremder Anwendung auslesen
 
Also ich mache das etwa so (keine injection, dafür aber debugging-Rechte) ...

Delphi-Quellcode:
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;
Referenz: http://www.delphipraxis.net/internal...t.php?t=166858

mw19 1. Mär 2010 17:37

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

Fridolin Walther 1. Mär 2010 17:44

Re: Startparameter fremder Anwendung auslesen
 
Die bekommst Du hier:
http://blog.delphi-jedi.net/jedi-api-headers/

Dezipaitor 1. Mär 2010 22:38

Re: Startparameter fremder Anwendung auslesen
 
Du brauchst keine Debuggingrechte, wenn du nur deine eigenen Prozesse öffnen willst. Lass das also weg.

mw19 2. Mär 2010 07:40

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 15:58 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