Recent

Author Topic: Launching external CMD application, and waiting for it to exit?  (Read 850 times)

FiftyTifty

  • Jr. Member
  • **
  • Posts: 56
Got a wee bit of an issue with both ExecuteProcess, and ShellExecute. I've made a command line tool, which calls another command line tool.

Here are the calls:

Code: Pascal  [Select][+][-]
  1. ExecuteProcess(strAppDir + 'bsarch.exe', strCommandLine, []);
  2.  
  3.                 if ShellExecute(0, nil, PChar(strAppDir + 'bsarch.exe'), PChar(strCommandLine), nil, 1) > 32 then
  4.         WriteLn('BSArch Success! ');

The commands are valid. But there are two problems.

ExecuteProcess Needs the file to have all permissions for user accounts, which is a total faff for the end user. Especially when I'm not writing to the file, just reading it. There is no documentation for TExecuteFlags, so I've no idea what to put in [].

ShellExecute Works, but the external program is ran and my code continues after it has launched. What I want to do, is run the program, and wait for it to close automatically.

How do I go about this?

Bart

  • Hero Member
  • *****
  • Posts: 5290
    • Bart en Mariska's Webstek
Re: Launching external CMD application, and waiting for it to exit?
« Reply #1 on: April 11, 2022, 06:43:46 pm »
Why not use TProcess?
Include opWaitForExit in it's options.

Bart

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11451
  • FPC developer.
Re: Launching external CMD application, and waiting for it to exit?
« Reply #2 on: April 11, 2022, 06:58:02 pm »
TProcess (and its easier sibbling Runcommand) also use CreateProcess, so the permissions probably also be a problem there.

But if the permissions for the target differ from your own, keeping control over it will be hard any which way, since if you could launch an executable with higher permissions yet control it, you essentially would have increased your permissions?

FiftyTifty

  • Jr. Member
  • **
  • Posts: 56
Re: Launching external CMD application, and waiting for it to exit?
« Reply #3 on: April 11, 2022, 07:59:05 pm »
Why not use TProcess?
Include opWaitForExit in it's options.

Bart

TProcess Looked like a bit of a cludge, while the other two commands looked much easier to work with. I won't be needing to capture the output, so it should be okay if I use the simple example from with Wiki, yeah?

TProcess (and its easier sibbling Runcommand) also use CreateProcess, so the permissions probably also be a problem there.

But if the permissions for the target differ from your own, keeping control over it will be hard any which way, since if you could launch an executable with higher permissions yet control it, you essentially would have increased your permissions?

It's odd. If I call the program from CMD, it works just fine with the exact same arguments. But if I call it through ExecuteProcess(), it doesn't work. But ShellExecute does?

I'd like to have a go at ShllExecuteEx, but the docs were designed with a Forms application, rather a command line one like I've got. Any idea how I work with that?

Edit: TProcess was the way to go. It just works. Here's my code that calls it:

Code: Pascal  [Select][+][-]
  1. procedure ExtractArchives(out tstrlistArchives: TStringList);
  2. var
  3.    processBSArch: TProcess;
  4.    strCommandLine, strCurrent: string;
  5.    iCounter: integer;
  6. begin
  7.  
  8.   FindAllFiles(tstrlistArchives, strAppDir, '*.bsa', false);
  9.  
  10.   for iCounter := tstrlistArchives.Count - 1 downto 0 do begin
  11.  
  12.     strCurrent := StringReplace(ExtractFileName(tstrlistArchives[iCounter]), '.bsa', '', []);
  13.  
  14.     WriteLn( 'Found archive: ' + strCurrent );
  15.  
  16.     if tstrlistBSAArchiveNames.IndexOf( strCurrent ) = -1 then
  17.         tstrlistArchives.Delete(iCounter);
  18.  
  19.   end;
  20.  
  21.   WriteLn('Number of archives: ' + IntToStr(tstrlistArchives.Count));
  22.  
  23.   for iCounter := 0 to tstrlistArchives.Count - 1 do begin
  24.  
  25.     WriteLn('Iterating!');
  26.  
  27.     processBSArch := TProcess.Create(nil);
  28.           processBSArch.Options := processBSArch.Options + [poWaitOnExit];
  29.  
  30.     strCurrent := tstrlistArchives[iCounter];
  31.  
  32.     WriteLn(strCurrent);
  33.  
  34.     strCurrent := StringReplace(strCurrent, '.bsa', '', []);
  35.     CreateDir(strCurrent);
  36.  
  37.     strCommandLine := strAppDir + 'bsarch.exe ' + 'unpack "' +
  38.                                                                         tstrlistArchives[iCounter] + '" "' + strCurrent + '\"';
  39.  
  40.     WriteLn(strCommandLine);
  41.  
  42.           processBSArch.Executable := strCommandLine;
  43.     processBSArch.Execute;
  44.  
  45.     processBSArch.Free;
  46.  
  47.   end;
  48.  
  49. end;
« Last Edit: April 12, 2022, 03:03:44 am by FiftyTifty »

Zvoni

  • Hero Member
  • *****
  • Posts: 2327
Re: Launching external CMD application, and waiting for it to exit?
« Reply #4 on: April 12, 2022, 09:52:09 am »
Your Line 10 to 19
How is that supposed to work?
FindAllFiles returns the Full path to a File (e.g. "c:\test\SomeFolder\SomeFile.bsa")
In Line 12 you extract the Filename ("SomeFile.bsa") and remove the Extension, resulting in "SomeFile"
In Line 16 you look in your StringList for the Index of "SomeFile" --> which is never going to be found! resulting in, basically, emptying out the StringList again.

Or did i miss something?
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11451
  • FPC developer.
Re: Launching external CMD application, and waiting for it to exit?
« Reply #5 on: April 12, 2022, 10:01:04 am »
And executable is just the exe, not the cmdline.

 

TinyPortal © 2005-2018