How to capture external dos commands of external applications? lazarus / 34-Windows ---------------------------------------------------------------------- loaded · 2023-03-29 05:20 Hi All, I can see the dos commands or applications run by an external application in Process Explorer. Views are attached below. I want to keep records of what commands and applications a particular application is running. Is there a simple way to do this? Or should I continue to use Process Explorer? ---------------------------------------------------------------------- KodeZwerg · 2023-03-29 08:20 About the used command line I can not tell much since I never investigated that deep but for your treeview on your app to show what other processes your app has started I would call the NtQueryInformationProcess method and use "InheritedFromUniqueProcessId" from the build output record to compare that PID against your apps PID to know that it belongs to that process. ---------------------------------------------------------------------- KodeZwerg · 2023-03-29 08:35 I guess I explained it a little wrong, with the NtQueryInformationProcess you get a back an array of record of all processes with further information like InheritedFromUniqueProcessId (what represent the owner/parent) So you need first to build that record and afterwards parse it to sort what PID belong to whom. I hope that was more clear. ---------------------------------------------------------------------- laguna · 2023-03-29 09:43 with this code output dos is show in memo in realtime Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  //...   public         procedure ProcessEvent(Sender,Context : TObject;Status:TRunCommandEventCode;const Message:string);   end;   TProcessToMemo = class(TProcess)                             public                           fmemo : Tmemo;                             bytesprocessed : integer;                             fstringsadded : integer;                             function ReadInputStream(p:TInputPipeStream;var BytesRead:integer;var DataLength:integer;var Data:string;MaxLoops:integer=10):boolean;override;                         end;    varForm1: TForm1;   implementation {$R *.lfm} { TForm1 }     function RunCommandMemo(const exename:TProcessString;const commands:array of TProcessString;out outputstring:string; Options : TProcessOptions = [];SWOptions:TShowWindowOptions=swoNone;memo:TMemo=nil;runrefresh : TOnRunCommandEvent=nil ):boolean;    Var        p : TProcessToMemo;      i,        exitstatus : integer;        ErrorString : String;    begin      p:=TProcessToMemo.create(nil);      if Options<>[] then      P.Options:=Options - [poRunSuspended,poWaitOnExit];      p.options:=p.options+[poRunIdle, poNoConsole];       P.ShowWindow:=SwOptions;      p.Executable:=exename;      if high(commands)>=0 then       for i:=low(commands) to high(commands) do         p.Parameters.add(commands[i]);      p.fmemo:=memo;      p.OnRunCommandEvent:=runrefresh;      try        result:=p.RunCommandLoop(outputstring,errorstring,exitstatus)=0;      finally        p.free;      end;      if exitstatus<>0 then result:=false;    end;    procedure TForm1.ProcessEvent(Sender, Context: TObject;      Status: TRunCommandEventCode; const Message: string);    begin      if status in [RunCommandIdle, RunCommandFinished] then        begin          if status =RunCommandFinished then            begin              memo1.lines.add(' process finished');            end;          if tprocesstomemo(sender).fstringsadded>0 then           begin           tprocesstomemo(sender).fstringsadded:=0;    //         memo1.lines.ad d('Handle:'+inttostr(tprocesstomemo(sender).ProcessHandle));           memo1.refresh;           end;          sleep(10);          application.ProcessMessages;        end;    end;     { TProcessToMemo }      function TProcessToMemo.ReadInputStream(p:TInputPipeStream;var BytesRead:integer;var DataLength:integer;var Data:string;MaxLoops:integer=10):boolean;    var lfpos : integer;      crcorrectedpos:integer;        stradded : integer;        newstr : string;    begin      Result:=inherited ReadInputStream(p, BytesRead, DataLength, data, MaxLoops);      if (result) and (bytesread>bytesprocessed)then        begin          stradded:=0;        lfpos:=pos(#10,data,bytesprocessed+1);          while (lfpos<>0) and (lfpos<=bytesread) do            begin              crcorrectedpos:=lfpos;              if (crcorrectedpos>0) and (data[crcorrectedpos-1]=#13) then                 dec(crcorrectedpos);              newstr:=copy(data,bytesprocessed+1,crcorrectedpos-bytesprocessed-1);            fmemo.lines.add(newstr);               inc(stradded);            bytesprocessed:=lfpos;              lfpos:=pos(#10,data,bytesprocessed+1);            end;          inc(fstringsadded,stradded); // check idle event.        end;    end; begin  RunCommandMemo('python.exe',['fec.py',username.Text,Codice Pin.Text,Password.Text,Piva.Text, DateToStr(DataDal.date,fmt) , DateToStr(DataDal.date,fmt) , Serv],s,[],swonone,memo1,@ProcessEvent);end. ---------------------------------------------------------------------- loaded · 2023-03-29 11:54 Thank you all so much for taking your precious time to reply. KodeZwerg; In the picture above, the cmd process is waiting for confirmation from the user to terminate it permanently. However, some commands can run and terminate very quickly without waiting for confirmation. I need to catch them too. So it seems to me that I need to somehow capture a message from the operating system. It would be worth the effort if it could be done in a simple way, but I don't need to go too deep right now. laguna ; I think I was misunderstood, I don't have a need for routing commands to the pipe. Consider that the application in the picture does not belong to me. I wanted to know what commands (not just dos) an external application is running after this application is running. ---------------------------------------------------------------------- KodeZwerg · 2023-03-29 13:04 If you just need such for your own application, TProcess would be a good choice by using the poWaitOnExit option to inform your app when the process has finished (closed/terminated). Anyway, that approach does not cover if the launched process open more. CreateToolhelp32Snapshot/TProcessEntry32 or NtQueryInformationProcess are the things to be used to really cover everything. ---------------------------------------------------------------------- loaded · 2023-03-29 13:08 Quote from: KodeZwerg on March 29, 2023, 03:04:28 pmCreateToolhelp32Snapshot/TProcessEntry32 or NtQueryInformationProcess are the things to be used to really cover everything. Thanks for the info, I'll look into them as soon as possible.