Recent

Author Topic: How to make RunCommand NOT wait on exection  (Read 646 times)

zxandris

  • Full Member
  • ***
  • Posts: 152
How to make RunCommand NOT wait on exection
« on: March 07, 2025, 11:39:34 pm »
Hey I'm trying to run an external program, with parameters but I don't actually want it to wait on execution.  I've tried quite a few things and currently have :-

Code: Pascal  [Select][+][-]
  1. RunCommand(exeFile, cline, GOutP, [poNoConsole], swoShowNormal);

This just waits for execution is there a way to stop it doing that please?

cJ

n7800

  • Sr. Member
  • ****
  • Posts: 280
Re: How to make RunCommand NOT wait on exection
« Reply #1 on: March 08, 2025, 12:42:55 am »
There is a great article on the wiki that answers all the questions about calling an external program:

https://wiki.freepascal.org/Executing_External_Programs

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12142
  • FPC developer.
Re: How to make RunCommand NOT wait on exection
« Reply #2 on: March 08, 2025, 11:38:57 am »
Runcommand was written to encapsulate the TProcess scenario where you want to wait.

If not, then you will have to use TProcess directly.

You need to have some check on process end, since the TProcess instance needs to be freed.

If you just want to fire and forget, on Windows try shellexecute. On Unix I don't know because afaik there it is the job of the called EXE to cut the cord rather than the one calling it.

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 370
  • My software never cras....
Re: How to make RunCommand NOT wait on exection
« Reply #3 on: March 09, 2025, 08:50:06 pm »
Hey I'm trying to run an external program, with parameters but I don't actually want it to wait on execution.  I've tried quite a few things and currently have :-

Code: Pascal  [Select][+][-]
  1. RunCommand(exeFile, cline, GOutP, [poNoConsole], swoShowNormal);

This just waits for execution is there a way to stop it doing that please?


I do such via threads.  Using flags or status to tell the invoking procedure (or another) to determine if the command has completed.

The other thread can signal completion in various ways.  I like to use the pointer passed to the thread to point at a boolean or state value (care to make sure the stack hasn't released, or messily with a global as below).

Here is a hastily written and tested program (that works on a mac in Terminal) where the command is running in a thread detached from the main thread:
(You'll need to complete the wrapper - I added this to an existing program - don't forget to add cthreads and classes to the uses clause).
Adjust the command for whatever OS you're on, (and the RunCommand details).

So for your purpose the "de-coupling" occurs on the BeginThread call.  How you "rendez-vous" for the result is entirely up to your imagination.

You can also use a call to BeginThread, get the ThreadID and then have a different proc or function WaitForThreadTerminate (TID).

Code: Pascal  [Select][+][-]
  1. VAR
  2.         SexIsFunTerminated: boolean;
  3.         SexIsFunString: ansistring;
  4.        
  5. Function SexIsFun (p:pointer):ptrint;
  6. VAR
  7.         Q : ansistring;
  8.         Result: ansistring;
  9. BEGIN
  10.         Q := ansistring(p^);   // get the command from the invoker
  11.  
  12.         RunCommand ('/bin/sh',['-c',Q],Result);
  13.        
  14.         ansistring(p^) := Result;  //replace the command with the result (yes: clumsy - but you can figure out better ways
  15.         SexIsFunTerminated := true;
  16.                
  17.         exit(0);
  18. END;
  19.  
  20. Procedure IssueFreedCommand;
  21. BEGIN
  22.         SexIsFunTerminated := false;
  23.         SexIsFunString := 'ls -al';                      //the command to be passed with the RunCommand function (this is Unix / Linux compatible)*
  24.         BeginThread (@SexIsFun, @SexIsFunString);
  25. END;
  26.  
  27. Procedure SexConnection;
  28. VAR
  29.         T: ansistring;
  30. BEGIN
  31.         // do something useful, then
  32.         While NOT SexIsFunTerminated do sleep (100);
  33.         Writeln (SexIsFunString);
  34. END;
  35.  
  36. Procedure Sex;
  37. BEGIN
  38.         IssueFreedCommand;
  39.         SexConnection;
  40. END;

* I believe there is a Windows extension (?) of sorts that gives windows' terminal "Unix like" commands - but not sure

« Last Edit: March 09, 2025, 10:04:24 pm by AlanTheBeast »
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

AlanTheBeast

  • Sr. Member
  • ****
  • Posts: 370
  • My software never cras....
Re: How to make RunCommand NOT wait on exection
« Reply #4 on: March 09, 2025, 10:11:20 pm »
If you just want to fire and forget, on Windows try shellexecute. On Unix I don't know because afaik there it is the job of the called EXE to cut the cord rather than the one calling it.

On Unix (or Mac anyway) you can "fire and forget" by making the command string something like:

   CMD : ansistring = '/Users/Bob/Applications/keepawkeawake3 & disown';
...
...
        Result := RunCommand ('/bin/zsh',['-c',CMD],S);


This creates a separate system owned thread, no terminal window is opened for it.

But that isn't what the OP wants (I believe).
« Last Edit: March 09, 2025, 10:27:40 pm by AlanTheBeast »
Everyone talks about the weather but nobody does anything about it.
..Samuel Clemens.

Aruna

  • Hero Member
  • *****
  • Posts: 627
Re: How to make RunCommand NOT wait on exection
« Reply #5 on: March 10, 2025, 02:41:33 am »
Hey I'm trying to run an external program, with parameters but I don't actually want it to wait on execution.  I've tried quite a few things and currently have :-
Code: Pascal  [Select][+][-]
  1. RunCommand(exeFile, cline, GOutP, [poNoConsole], swoShowNormal);
This just waits for execution is there a way to stop it doing that please?
cJ

If your on Windows try:
Code: Pascal  [Select][+][-]
  1. RunCommand(exeFile, cline, GOutP, [poNoConsole, poDetached], swoShowNormal);

poDetached — What it does

When you include poDetached in TProcess.Options, it detaches the child process from the parent process. That means:
    The new process is launched independently.
    It won’t be tied to your Lazarus process (no wait happens).
    Your program does not wait for it to finish.

Documentation for poDetached- Runs a process using the DETACHED_PROCESS creation flag on Windows


If you are on Linux you can do something along this:
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,Process;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     procedure Button1Click(Sender: TObject);
  17.   private
  18.  
  19.   public
  20.  
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.lfm}
  29.  
  30. { TForm1 }
  31.  
  32. procedure TForm1.Button1Click(Sender: TObject);
  33.  
  34. var
  35.   AProcess: TProcess;
  36. begin
  37.   AProcess := TProcess.Create(nil);
  38.   try
  39.     AProcess.Executable := '/usr/bin/ls';  // FULL PATH REQUIRED!
  40.     AProcess.Parameters.Add('-1alh');      // Add any flags/switches you want to the command here
  41.     AProcess.Options := [poDetached];      //
  42.     AProcess.Execute;
  43.   finally
  44.     AProcess.Free;
  45.   end;
  46. end;
  47. end.
  48.  

It helps immensely if you tell us what your OS is and what specific command you're trying to run. Sharing the code is the best way to get people to help you. Good luck!
« Last Edit: March 10, 2025, 02:50:29 am by Aruna »

zxandris

  • Full Member
  • ***
  • Posts: 152
Re: How to make RunCommand NOT wait on exection
« Reply #6 on: March 15, 2025, 03:17:07 pm »
I'm actually using windows 11 I mean specifically, but this could be run on any windows I imagine and as for the exact thing I'm running I don't know.  This is to allow my end user to specify an application to run with certain params.  Now that generally works and I've been using TProcess to run without waiting.  I was just hoping for the sake of clarity I could use RunCommand.  I did post my code there that's actually used but it really changes everytime.  But for the sake of hoping this helps this is a windows application.  I will try detached options see if that allows me to do this.

Thank you so much for all your help guys, it certainly has actually helped me!

CJ

 

TinyPortal © 2005-2018