Recent

Author Topic: run external app wait to load  (Read 4249 times)

Fibonacci

  • Hero Member
  • *****
  • Posts: 952
  • Behold, I bring salvation - FPC Unleashed
Re: run external app wait to load
« Reply #15 on: February 07, 2024, 04:28:07 am »
All these examples wait for an app to EXIT. Either waiting for window to close, or for process to close.
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

Thaddy

  • Hero Member
  • *****
  • Posts: 19181
  • Glad to be alive.
Re: run external app wait to load
« Reply #16 on: February 07, 2024, 07:01:10 am »
It should be possible with TProcess like this:
Check Process.Running immediately after execute , something like so:
Code: Pascal  [Select][+][-]
  1. [s]while not process.running do begin write('.');sleep(100);end;
  2. writeln('process has been loaded, now executing';
This was in my head yesterday, but I forgot to explain that.

Another is possibly to attach an OnRunCommandLoop event and check how long the process is signalled as idle https://www.freepascal.org/docs-html/fcl/process/truncommandeventcode.html[/s]
but I need to test that. Would be more elegant if that works. That is that I suspect that during loading the process is idle. If so I will attach an example.[/s]


EDIT Both options do not work as I expected.
« Last Edit: February 07, 2024, 08:24:19 am by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: run external app wait to load
« Reply #17 on: February 07, 2024, 10:45:55 am »
If target is windows you could try your luck also by checking the last access time value (GetFileTime()) in a TTimer, but this needs that the system support it.
If such method is available in a crosscompile way I do not know.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12866
  • FPC developer.
Re: run external app wait to load
« Reply #18 on: February 07, 2024, 11:46:19 am »
All these examples wait for an app to EXIT. Either waiting for window to close, or for process to close.

Yup. They are basically the kind of code that TProcess/Runcommand was meant to cleanup.

Thaddy

  • Hero Member
  • *****
  • Posts: 19181
  • Glad to be alive.
Re: run external app wait to load
« Reply #19 on: February 07, 2024, 12:20:40 pm »
I have an example here that overrides SysExecute which is the closest I could find to approximate load time, actual start of execution. My previous python example from another thread extended.
Code: Pascal  [Select][+][-]
  1. program pythonchecker;
  2. {$mode objfpc}{$H+}{$ifdef mswindows}{$apptype console}{$endif}
  3. uses classes, process, sysutils;
  4. type
  5. { TMyProcess }
  6. TMyProcess = class(TProcess)
  7. private
  8.   FStartTime,FLoadTime:Int64;
  9. public
  10.   constructor create(Aowner:TComponent);override;
  11.   procedure SysExecute;override;
  12.   procedure CheckLoading(Sender: TObject;Context: TObject;
  13.                  Status: TRunCommandEventCode;const Message: string);
  14.   property StartTime:Int64 read FStartTime;
  15.   property LoadTime:Int64 read FLoadTime;
  16. end;
  17.  
  18. var P:TProcess;
  19.  a,b:string;
  20.  c:integer;
  21.  
  22. { TMyProcess }
  23. constructor TMyProcess.create(Aowner: TComponent);
  24. begin
  25.   inherited create(Aowner);
  26.   OnRunCommandEvent := @CheckLoading;
  27. end;
  28.  
  29. procedure TMyProcess.SysExecute;
  30. begin
  31.   FLoadTime := 0;
  32.   FStartTime := GetTickCount64;
  33.   inherited SysExecute;// closest to process load, sets Tprocess.Running
  34. end;
  35.  
  36.  
  37. procedure TMyProcess.CheckLoading(Sender: TObject; Context: TObject;
  38.   Status: TRunCommandEventCode; const Message: string);
  39. begin
  40.   if LoadTime = 0 then
  41.   begin
  42.     // first time the event fires, close to actual start of execution.
  43.     FLoadTime :=GetTickCount64-StartTime;
  44.    // Approximates actual start of execution.
  45.     writeln(LoadTime,'ms load time');
  46.    end;
  47. end;
  48.  
  49. begin
  50.  P :=TMyProcess.Create(nil);
  51.  try
  52.    P.executable:='python3.exe';
  53.    P.Parameters.Add('-m');
  54.    P.Parameters.Add('py_compile');
  55.    P.Parameters.Add('hello.py');
  56.    P.Options :=[poStderrToOutPut,poRunIdle];
  57.    P.RunCommandLoop(a,b,c);
  58.    writeln(a,b);
  59.    writeln(c);
  60.    readln;
  61.  finally
  62.    P.Free;
  63.  end;
  64. end.  
This works by measuring the call to SysExecute and the first time the event occurs,
which is immediately after the process actually runs.
@victor11109
Can you test if that is enough?
« Last Edit: February 07, 2024, 02:53:03 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

victor11109

  • New Member
  • *
  • Posts: 19
Re: run external app wait to load
« Reply #20 on: February 08, 2024, 02:17:10 pm »
This works by measuring the call to SysExecute and the first time the event occurs,
which is immediately after the process actually runs.
Can you test if that is enough?

thanks -- i put code in lazarus and get error  Error: identifier idents no member "SysExecute" but any way maybe missing something  ::) . i tested in codetyphon but its just like others will wait to exit the app then will cuntinue . also the cpu going to 80% work i think because of that loopcommand .

Thaddy

  • Hero Member
  • *****
  • Posts: 19181
  • Glad to be alive.
Re: run external app wait to load
« Reply #21 on: February 08, 2024, 02:22:57 pm »
sysexecute should always work. It does for me but I am always on trunk. But my class should work cross platform. (It does) Note it is also documented so it is part of FPC 3.2.2 classes too.
The class is a simple extension to TProcess that does some timing.
The first time the event is fired means the program is fully loaded.
So it can even be simpler.
Maybe you are confused: it is TThread.SysExecute, there is no sysexecute on its own.

(For  good measure, I analysed the sourcecode for what it actually does and in what order)
« Last Edit: February 08, 2024, 02:40:12 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12866
  • FPC developer.
Re: run external app wait to load
« Reply #22 on: February 08, 2024, 03:49:47 pm »
I have a slightly different version that aborts batch executions if they take to long

Code: Pascal  [Select][+][-]
  1. {$mode delphi}
  2. uses Windows,classes,sysutils,process,dateutils,rennameutils;
  3.  
  4. Type
  5. { TProcessTimeout }
  6.  TProcessTimeout = class(TProcess)
  7.                             public
  8.                             timeoutperiod: TTime;
  9.                             timedout : boolean;
  10.                             started : TDateTime;
  11.                             procedure LocalnIdleSleep(Sender,Context : TObject;status:TRunCommandEventCode;const message:string);
  12.                           end;
  13.  
  14. procedure TProcessTimeout.LocalnIdleSleep(Sender,Context : TObject;status:TRunCommandEventCode;const message:string);
  15. begin
  16.    if status=RunCommandIdle then
  17.     begin
  18.       if (now-started)>timeoutperiod then
  19.          begin
  20.            timedout:=true;
  21.            Terminate(255);
  22.            exit;
  23.          end;
  24.       sleep(RunCommandSleepTime);
  25.     end;
  26. end;
  27.  
  28. function RunCommandTimeout(const exename:TProcessString;const commands:array of TProcessString;out outputstring:string; Options : TProcessOptions = [];SWOptions:TShowWindowOptions=swoNone;timeout:integer=60):boolean;
  29. // timeout is in seconds
  30. Var
  31.     p : TProcessTimeout;
  32.     i,
  33.     exitstatus : integer;
  34.     ErrorString : String;
  35. begin
  36.   p:=TProcessTimeout.create(nil);
  37.   p.OnRunCommandEvent:=p.LocalnIdleSleep;
  38.   p.timeoutperiod:=timeout/SecsPerDay;
  39.   if Options<>[] then
  40.     P.Options:=Options - [poRunSuspended,poWaitOnExit];
  41.   p.options:=p.options+[poRunIdle];
  42.  
  43.   P.ShowWindow:=SwOptions;
  44.   p.Executable:=exename;
  45.   if high(commands)>=0 then
  46.    for i:=low(commands) to high(commands) do
  47.      p.Parameters.add(commands[i]);
  48.   p.timedout:=false;
  49.   p.started:=now;
  50.   try
  51.     result:=p.RunCommandLoop(outputstring,errorstring,exitstatus)=0;
  52.     if p.timedout then
  53.       result:=false;
  54.   finally
  55.     p.free;
  56.   end;
  57.   if exitstatus<>0 then result:=false;
  58. end;
  59.  

You can see the sleep I put in there to avoid the 100%.

 

TinyPortal © 2005-2018