Recent

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

victor11109

  • New Member
  • *
  • Posts: 19
run external app wait to load
« on: February 05, 2024, 09:06:02 pm »
Hellow anyone
Have code that run external app in windows and that app takes time to load . Currently using Tprocess to do this but haven't finde any thing that hold my app to finish that external app loading . I know about waitonexit but that wait for exit not finish load . Any one can help ?

Fibonacci

  • Hero Member
  • *****
  • Posts: 997
  • Behold, I bring salvation - FPC Unleashed
Re: run external app wait to load
« Reply #1 on: February 05, 2024, 09:08:14 pm »
How do you know if a process is "loaded"?
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: run external app wait to load
« Reply #2 on: February 05, 2024, 09:11:39 pm »
Hellow anyone
Have code that run external app in windows and that app takes time to load . Currently using Tprocess to do this but haven't finde any thing that hold my app to finish that external app loading . I know about waitonexit but that wait for exit not finish load . Any one can help ?
Can you please rephrase everything and write down in steps what you actual want to achieve.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

Thaddy

  • Hero Member
  • *****
  • Posts: 19262
  • Glad to be alive.
Re: run external app wait to load
« Reply #3 on: February 05, 2024, 09:17:53 pm »
Use TProcess.RunCommandLoop and TProcess.OnRunCommandEvent.
See the manual.
https://www.freepascal.org/docs-html/fcl/process/tprocess.runcommandloop.html
https://www.freepascal.org/docs-html/fcl/process/tprocess.onruncommandevent.html
https://www.freepascal.org/docs-html/fcl/process/tonruncommandevent.html
https://www.freepascal.org/docs-html/fcl/process/truncommandeventcode.html

And test for RunCommandFinished and probably RunCommandException and RunCommandIdle too.
It is not as complex as it reads...  :D Actually, not at all.
I put everything in logical order. Just read it..

It is just:
1. Create a Tprocess
2. Write a TOnRunCommand method and attach it to the OnRunCommand.
3. Add all the parameters to TProcess
4. Call RunCommandLoop
5. Test in OnRunCommand for the three I mentioned above. (or all possible)

That is really all.

(There are also WAY more difficult alternatives that I would forbid you do not recommend to use them. The non-manual (non-)readers will no doubt try to add their "better" solution. Trust me, there is not a better than the above.)
« Last Edit: February 05, 2024, 09:37:34 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 #4 on: February 05, 2024, 10:17:52 pm »
Hellow anyone
Have code that run external app in windows and that app takes time to load . Currently using Tprocess to do this but haven't finde any thing that hold my app to finish that external app loading . I know about waitonexit but that wait for exit not finish load . Any one can help ?
Can you please rephrase everything and write down in steps what you actual want to achieve.


have external cmd app that run and read from config file and stay open to work - but reading that config file will take some time.
so i first make configfile for that then execute external app but want to delete config file after it finish load that file . if i delete config file after execution the external app will not work because its not finished loading that config file

here is my part of code that wont work  :):

```
        MyProcess := TProcess.Create(nil);
        MyProcessExecutable := 'externalApp.exe';
        MyProcess.Parameters.Add('run');
        MyProcess.Parameters.Add('-c');
        MyProcess.Parameters.Add('configFile.txt');
        MyProcess.Options := [poNoConsole];
        MyProcess.ShowWindow := swoHIDE;

        AssignFile(configFile, 'configFile.txt');
        try
          Rewrite(configFile);
          WriteLn(configFile, configData);
          CloseFile(configFile);
          MyProcess.Execute;
          DeleteFile('configFile.txt');   

```                     

Fibonacci

  • Hero Member
  • *****
  • Posts: 997
  • Behold, I bring salvation - FPC Unleashed
Re: run external app wait to load
« Reply #5 on: February 05, 2024, 10:28:49 pm »
Easy way is to add some Sleep() after execution.

Harder way is to catch StdOut in a loop, after you read that the config has been processed just escape the loop.

Here are some examples using pipes to read process output:
https://wiki.freepascal.org/Executing_External_Programs

Also you can try to check file last access time in a loop, and if it changes, escape the loop and delete the file.
FPC Unleashed - inline vars, tuples, statement expressions, array equality, compound assignments, indexed/lazy labels, no-RTTI & more. ⭐ Star it on GitHub!

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: run external app wait to load
« Reply #6 on: February 05, 2024, 10:40:13 pm »
I agree to Fibonacci or if you have source of the app that you execute you can IPC to host that is has loaded the file.
There are not much possibilites. If its Windows you might find out if a handle is still attached to that file.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

victor11109

  • New Member
  • *
  • Posts: 19
Re: run external app wait to load
« Reply #7 on: February 05, 2024, 10:53:44 pm »
Use TProcess.RunCommandLoop and TProcess.OnRunCommandEvent.
See the manual.
https://www.freepascal.org/docs-html/fcl/process/tprocess.runcommandloop.html
https://www.freepascal.org/docs-html/fcl/process/tprocess.onruncommandevent.html
https://www.freepascal.org/docs-html/fcl/process/tonruncommandevent.html
https://www.freepascal.org/docs-html/fcl/process/truncommandeventcode.html

And test for RunCommandFinished and probably RunCommandException and RunCommandIdle too.
It is not as complex as it reads...  :D Actually, not at all.
I put everything in logical order. Just read it..

It is just:
1. Create a Tprocess
2. Write a TOnRunCommand method and attach it to the OnRunCommand.
3. Add all the parameters to TProcess
4. Call RunCommandLoop
5. Test in OnRunCommand for the three I mentioned above. (or all possible)

That is really all.

(There are also WAY more difficult alternatives that I would forbid you do not recommend to use them. The non-manual (non-)readers will no doubt try to add their "better" solution. Trust me, there is not a better than the above.)


i write what i want to do for KodeZwerg . now are you think your way solve the problem ? i will go check the RunCommandLoop . but need more help for that if its the way . tanks to take time . im a little noob  :D
 

victor11109

  • New Member
  • *
  • Posts: 19
Re: run external app wait to load
« Reply #8 on: February 05, 2024, 11:03:55 pm »
I agree to Fibonacci or if you have source of the app that you execute you can IPC to host that is has loaded the file.
There are not much possibilites. If its Windows you might find out if a handle is still attached to that file.

yes i do a lot search and even ChatGPT not undrestanding and give me waitOnExit code sample  :D
any way for now use sleep() to solve but if you familiar with App called VisualNeoWIn that created By Delphi has something that i looking For
and its created by delphi so  the method shoud not have too much diffrence from Lazarus/delphi because its other methods are same as Lazarus/delphi

thanks for helps  ::)

jamie

  • Hero Member
  • *****
  • Posts: 7763
Re: run external app wait to load
« Reply #9 on: February 05, 2024, 11:28:24 pm »
use the SingleWaitObject(ProcessID,....)

 This may not work if the known bug with the TProcess.ProcessID never got fixed for windows.

so, if this is a windows target then use the direct API to start the process, at lease you'll have a valid processID to use in a Wait object.

The only true wisdom is knowing you know nothing

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: run external app wait to load
« Reply #10 on: February 05, 2024, 11:48:05 pm »
I agree to Fibonacci or if you have source of the app that you execute you can IPC to host that is has loaded the file.
There are not much possibilites. If its Windows you might find out if a handle is still attached to that file.

yes i do a lot search and even ChatGPT not undrestanding and give me waitOnExit code sample  :D
any way for now use sleep() to solve but if you familiar with App called VisualNeoWIn that created By Delphi has something that i looking For
and its created by delphi so  the method shoud not have too much diffrence from Lazarus/delphi because its other methods are same as Lazarus/delphi

thanks for helps  ::)
If that VisualNeoWIn thing is written in Delphi and a solution to your problem, than it is of course also in Lazarus/FreePascal possible.
Attach source code and we help to convert it.
use the SingleWaitObject(ProcessID,....)
He can of course use CreateProcess() on its own but what does he get by using SingleWaitObject beside that something is active or not?
He stated that he call an external application, that external does load a file that his "launcher" creates and for some unknown reason he wants that this file gets deleted while the other application is still running.

My quick and dirty solution would be, create that mysterious file in a temp folder somewhere inside roaming, get yourself notified when target app is closed to delete it or when you close your "launcher" to delete it. The temp folder and filename is something that you have under your control so you can name it with random numbers or letters etc.... just an idea.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

victor11109

  • New Member
  • *
  • Posts: 19
Re: run external app wait to load
« Reply #11 on: February 06, 2024, 12:04:17 am »
I agree to Fibonacci or if you have source of the app that you execute you can IPC to host that is has loaded the file.
There are not much possibilites. If its Windows you might find out if a handle is still attached to that file.

yes i do a lot search and even ChatGPT not undrestanding and give me waitOnExit code sample  :D
any way for now use sleep() to solve but if you familiar with App called VisualNeoWIn that created By Delphi has something that i looking For
and its created by delphi so  the method shoud not have too much diffrence from Lazarus/delphi because its other methods are same as Lazarus/delphi

thanks for helps  ::)
If that VisualNeoWIn thing is written in Delphi and a solution to your problem, than it is of course also in Lazarus/FreePascal possible.
Attach source code and we help to convert it.
use the SingleWaitObject(ProcessID,....)
He can of course use CreateProcess() on its own but what does he get by using SingleWaitObject beside that something is active or not?
He stated that he call an external application, that external does load a file that his "launcher" creates and for some unknown reason he wants that this file gets deleted while the other application is still running.

My quick and dirty solution would be, create that mysterious file in a temp folder somewhere inside roaming, get yourself notified when target app is closed to delete it or when you close your "launcher" to delete it. The temp folder and filename is something that you have under your control so you can name it with random numbers or letters etc.... just an idea.

VisualNeoWin app is closed source  :'(   the reason for wanting the configuration file to be deleted immediately, it is to prevent user access to that configuration file. Using a temporary folder is also a good idea . wonder is any way to prevent user access that file but app can access that file

jamie

  • Hero Member
  • *****
  • Posts: 7763
Re: run external app wait to load
« Reply #12 on: February 06, 2024, 12:16:50 am »
Oh, it's one of those things! :-[
The only true wisdom is knowing you know nothing

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2269
  • Fifty shades of code.
    • Delphi & FreePascal
Re: run external app wait to load
« Reply #13 on: February 06, 2024, 12:31:30 am »
wonder is any way to prevent user access that file but app can access that file
We do not know much about your "target.exe" file, maybe you can feed it with your configuration via a CLI pipe "<" or call that "target.exe" direct with your settings ... ?
AFAIK there is no way to prevent, when it is physical than it is exposed, no matter what.
Within your own application there are possibilities (but also such can be overridden, depend on how much a user is willing to spend time) but for 3rd party not.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

victor11109

  • New Member
  • *
  • Posts: 19
Re: run external app wait to load
« Reply #14 on: February 06, 2024, 10:32:58 pm »
wonder is any way to prevent user access that file but app can access that file
We do not know much about your "target.exe" file, maybe you can feed it with your configuration via a CLI pipe "<" or call that "target.exe" direct with your settings ... ?
AFAIK there is no way to prevent, when it is physical than it is exposed, no matter what.
Within your own application there are possibilities (but also such can be overridden, depend on how much a user is willing to spend time) but for 3rd party not.

some guy in visulneo forum give me a hint in delphi . can i send here to see whats he did ? maybe help to convert that in pascal  :D
as i review that hint i think its an other Wait For Exit Thing . will Sent Maybe you Better Undrestand That
This is What exactly he say :

```

Perhaps these hints will help:

procedure TForm1.Button1Click(Sender: TObject);
var HW:hwnd;
begin
ShellExecute(Handle,'open','C:\windows\notepad.exe',nil,nil,SW_SHOW); //run notepad
sleep(100); //sleep, or there won't be a window handel
hw:== FindWindow(vbNullString, "Calculator") // find the handle of the desired window (Use vbNullString to ignore the window class)
Windows.SetParent(hw,Handle); //make it a child window of your application
end;

 

***

 

The example shows how to start an external application from your program and wait for it to complete.

function ExecAndWait(const FileName,
Params: ShortString;
const WinState: Word): boolean; export;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
CmdLine: ShortString;
begin
{ Put the file name between quotation marks, respecting all spaces in Win9x names }
CmdLine := '"' + Filename + '" ' + Params;
FillChar(StartInfo, SizeOf(StartInfo), #0);
with StartInfo do
begin
cb := SizeOf(SUInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WinState;
end;
Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
{ Waiting for the application to complete }
if Result then
begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Free the Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end;
end;

And here is an example of calling this function:

ExecAndWait( 'C:\windows\calc.exe', '', SH_SHOWNORMAL)
Parameter FileName =Name of the external program.
Parameter Params = Parameters required to run an external program
Parameter WinState = Specifies how the window will be displayed:
We can also use the following constants for this parameter: SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_SHOWNORMAL
PS: This code was tested in delphi versions 3, 4 and 5.

It works in 7 just needs to be replaced:
cb := SizeOf(SUInfo);
на
cb := SizeOf(StartInfo);

 

***

 

The example shows how to start an external application from your program and wait for it to complete.

01
function ExecAndWait(const FileName,
02
Params: ShortString;
03
const WinState: Word): boolean; export;
04
var
05
StartInfo: TStartupInfo;
06
ProcInfo: TProcessInformation;
07
CmdLine: ShortString;
08
begin
09
{ Put the file name between quotation marks, respecting all spaces in Win9x names }
10
CmdLine := '"' + Filename + '" ' + Params;
11
FillChar(StartInfo, SizeOf(StartInfo), #0);
12
with StartInfo do
13
begin
14
cb := SizeOf(SUInfo);
15
dwFlags := STARTF_USESHOWWINDOW;
16
wShowWindow := WinState;
17
end;
18
Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
19
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
20
PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
21
{ Waiting for the application to complete }
22
if Result then
23
begin
24
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
25
{ Free the Handles }
26
CloseHandle(ProcInfo.hProcess);
27
CloseHandle(ProcInfo.hThread);
28
end;
29
end;

And here is an example of calling this function:
1
ExecAndWait( 'C:windowscalc.exe', '', SH_SHOWNORMAL)
Parameter FileName = Name of the external program. Parameter Params = Parameters required to run an external program. Parameter WinState = Specifies how the window will be displayed: For this parameter we can also use the following constants: SW_HIDE, SW_MAXIMIZE, SW_MINIMIZE, SW_SHOWNORMAL

```
« Last Edit: February 06, 2024, 11:04:56 pm by victor11109 »

 

TinyPortal © 2005-2018