Bayesean Blog - Desktop, Mobile and IOT Developer Blog


Delphi command-line programs with DOSCommand

Posted on 1st Jun 2018 in Delphi FMX


DosCommand53.png

Background

When requiring a command –line program in your Application, setting up ‘createprocess ‘ and pipes is not that difficult. But it would be important to multithread your code so that your application is not stalled while your command-line application is running.

Save yourself the trouble as it is easier to use ‘DosCommand’.  Straight out, it is not a simple to use component as it looks?

Free Component

The TurboPack DOSCommand Component Information in Github indicates the following:-

This Component lets you execute a Dos program (exe, com or batch) and catch the output in order to put it in a memo. It states that the result should come back line by line.

You can download the Component from Github or through the GETIT Manager.

Limited examples can be found in the source Header and are a little outdated and lacking explanation.  

 Example App

 Here is an Example App set up with code that calls various exe(s) such as ipconfig etc. The code is available to download.

doscommand.gif

The Component

On reflection, the Component has been well written largely for Win32 and recently converted to Unicode and includes 64bit for VCL and FMX.

DosCommand is a multithreaded application comprising the following Classes:-

 

TProcessTimer

This is to stop the process after XXX seconds and cannot be accessed externally.

TInputLines

It is used to synchronise the ‘inputlines’ from main thread with ‘TDosThread’.

TSyncString

It synchronises ‘TReadPipe’ and ‘TDosThread’.

TReadPipe

First awaits for the pipe input then writes the pipe input to the ‘Tsynchstring ‘the event is then set and ’TDosthread’ then reads the input.

TDosthread - This thread awaits outputs through the pipe.

TDosCommand - forms the component which has the following.

public calls:-

Create;

Destroy;

Execute;

The user will call this to execute the command.

SendLine

Adds a line in the input pipe.

 Stop;

The user can stop the process with this method, stops process and waits.

EndStatus;

(esStop, stopped via ‘TDoscommand.Stop’.

esProcess,   ended via Child-Process.

esStill_Active,  still active.

esNone, not executed yet.

esError, ended via Exception.

 esTime); ended because of time.

 ExitCode;

 IsRunning;

When true, a command is still running.

 Lines;

 if the user want to access all the outputs of a process, lines are deleted before execution.

OutputLines;

This can be lines of a memo.

Priority;  

Stops process and waits, only for ‘createprocess’.

ProcessInformation;

Processinformation’ from ‘createprocess’.

CommandLine;

Creates a Command to execute.

CurrentDir;

This is the ‘currentdir’ for a child process. if empty then ‘currentdir’ is same as parent ‘currentdir’.

Environment;

This adda Environment variables to process. if empty then environment of parent process is used.

InputToOutput:

This checks if you want that the inputs to appear in the outputs as well.

MaxTimeAfterBeginning;MaxTimeAfterLastOutput;OnCharDecoding;OnCharEncoding;

These are events to convert ‘buf’ to ‘Unicodestring’ and reverse !! They are not needed if console of child uses an AnsiString!! This event is not threadsafe and there is no need to change this during execution.

OnExecuteError;

This event is fired if ‘DosCommand.execute’ is aborted via Exception.

OnNewChar;  

This event is fired for each New char that is received through the pipe.

OnNewLine;  

This event is fired for each New line that is received through the pipe.

OnTerminated;

This event is fired  for the ‘endofprocess’action, normally, time out or by ‘DosCommand.Stop’ action.

OnTerminateProcess;

This event is fired to ask for ‘processtermination’.

 

What functions don’t Work

I could not get results from the following functions:-  ‘Lines’, ‘Outputlines’ and ‘Environment(strings)’ as it resulted  in error outputs.

Extra Functions

Working with char decoding/encoding with on ‘newchar’ allows you to work with individual chars to process. I did not find the need to work with these functions unless extracting individual char outputs.

Making DosCommand Work

The easiest is to drop the DOScommand component, button and a memo on your form.

Start the code to check if DOScommand is running in the background. This will ensure that if you happen to rerun the process will not send error messages.

if DosCommand1.IsRunning then
  DosCommand1.Stop;

The source states that the timer will stop the process at the ‘maxtimeafterbeginning’ set time. However setting the default = 0 results in the process not starting or ending.

The source code ‘TThreadtimer’ requires a value > 0 to process. I found that with slower win32 cpu’s  that  ‘maxtimeafterOutput  =  30’ was the best fit for mixing 32bit and 64bit. Add the following code.

DosCommand1.InputtoOutput := false;
 DosCommand1.MaxTimeAfterBeginning := 1;
 DosCommand1.MaxTimeAfterLastOutput := 30;// Value  = 1  for a fast win64 multicore processor

(* you can type the directory directly*)
DosCommand1.CommandLine := GetEnvironmentVariable('COMSPEC');  // opens the CMD.exe

//Execute the code to open the CMD.exe in the applications folderpath.
DosCommand1.Execute;

Further processes are made with sendline……

The Boolean portion of Sendline works as follows:-

  • True creates  a  ‘ ’ (space) before the string.
  • false creates a   _ (Lowercasespace) before the string.
DosCommand1.SendLine(‘C:\Windows\System32\ ipconfig’, true); // will open the ipconfig.exe
DosCommand1.SendLine('', true); // equivalent to pressing the enter key

 To capture the processes to a memo use ‘dosCommandNewline’ procedure as follows:-

procedure TForm4.DosCommand1NewLine(ASender: TObject; const ANewLine: string;
  AOutputType: TOutputType);
begin
AOutputType:=otEntireLine;
memo1.Lines.Add(ANewline);  //Outputs the lines of the CMD.EXE
end;

 

To process after the exe has completed, use ‘dosCommandTerminated’ procedure. This ‘onterminate’ function is the only way to know if the multithreaded process has stopped running. This is handy if CMD is running a long running exe. The app waits till the end before processing more messages. No need to call ‘Application.processmessages’.

 

procedure TForm4.DosCommand1Terminated(Sender: TObject);
begin
//use this area to do something when the multithreaded process has completed/terminated
memo1.Lines.Add('Completed The Process...........');
end;

 

That should get you up and running.

Download the Example...

Download Code

Happy Coding


Be the First to Comment...

Add a Comment

9+5

Recent News

Delphi Delimited String to Fields
Delphi A Professional VCL DBGrid Part Four
Delphi A Professional VCL DBGrid Part Three
Delphi A Professional VCL DBGrid Part Two
Delphi A Professional VCL DBGrid Part One
Delphi VCL Buttons in DBGrid
Two Helper Apps for Delphi LibUSB
Delphi Libusb Library Introduction

Categories

Bootstrap 4
Delphi VCL
Delphi FMX
Ajax
Bootstrap 3
CSS
XE4>Delphi > XE4
Delphi < XE4
PHP

Archives

August 2019

Delphi Delimited String to Fields

June 2019

Delphi A Professional VCL DBGrid Part Four

May 2019

Delphi A Professional VCL DBGrid Part Three

April 2019

Delphi A Professional VCL DBGrid Part Two

March 2019

Delphi A Professional VCL DBGrid Part One

November 2018

Delphi VCL Buttons in DBGrid

October 2018

Two Helper Apps for Delphi LibUSB

September 2018

Delphi Libusb Library Introduction

August 2018

Delphi Object directly to a Json string in a REST Client
Delphi using Environment Variables in your App

July 2018

Delphi FMX Leaflet Plotter using OSM Maps

June 2018

C2PAS32 Convertor Application
C to Delphi Open Source Convertors Shootout
Delphi command-line programs with DOSCommand

May 2018

Delphi PDF Embedded viewer with PDF.js

March 2018

Delphi FMX - Changing TCharacter to TCharHelper
Make Your Delphi App POP using Javascript!

January 2018

Delphi FMX Dashboard using Chart.JS
Delphi FMX Form Docking

December 2017

PHP Slim REST Server & Delphi Auth Part 5

November 2017

Delphi FMX REST Client App Part 4

October 2017

Delphi VCL REST Pricing Client App Part 3

September 2017

Delphi REST VCL Client Basic Auth Part 2B

August 2017

Delphi REST Client Part 2A
PHP PDO REST Server Part 1

July 2017

PHP REST Server and Delphi Client Intro

June 2017

Delphi SQLite Encryptor-Decryptor Tool
Updating Applications Manifest using Delphi

May 2017

Create a Visual IP Address Geolocation with PHP

March 2017

PHP Downloader using Countdown timer
PHP File Downloader from a Inbox Selection

February 2017

Javascript Image-File Uploader with ThumbViewer

January 2017

Morris Charts and PHP-PDO

December 2016

CSS to create a functional Toggle Button