This is a new site that's currently running on alpha code. There are going to be bugs. If you discover any, please report them on the site's issues page (GitHub account required). Thanks.
Warning: Many URLs are going to change. Refer to the README file to discover which library project's documentation has been completed.
Applies to: ~>3.0
You will no doubt have seen a lot of code on the Internet that shows how to execute a console application and wait for it to complete. It will probably look something like this:
function ExecAndWait(const CommandLine: string): Boolean;
var
StartupInfo: Windows.TStartupInfo; // start-up info passed to process
ProcessInfo: Windows.TProcessInformation; // info about the process
ProcessExitCode: Windows.DWord; // process's exit code
begin
// Set default error result
Result := False;
// Initialise startup info structure to 0, and record length
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb := SizeOf(StartupInfo);
// Execute application commandline
if Windows.CreateProcess(nil, PChar(CommandLine),
nil, nil, False, 0, nil, nil,
StartupInfo, ProcessInfo) then
begin
try
// Now wait for application to complete
if Windows.WaitForSingleObject(ProcessInfo.hProcess, INFINITE)
= WAIT_OBJECT_0 then
// It's completed - get its exit code
if Windows.GetExitCodeProcess(ProcessInfo.hProcess,
ProcessExitCode) then
// Check exit code is zero => successful completion
if ProcessExitCode = 0 then
Result := True;
finally
// Tidy up
Windows.CloseHandle(ProcessInfo.hProcess);
Windows.CloseHandle(ProcessInfo.hThread);
end;
end;
end;
With the use if infinite waiting for the console application to complete, we can achieve the same result using TPJConsoleApp as follows:
function ExecAndWait2(const CommandLine: string): Boolean;
var
App: TPJConsoleApp;
begin
App := TPJConsoleApp.Create;
try
App.MaxExecTime := INFINITE; // don't time out
App.TimeSlice := INFINITE; // timeout for WaitForSingleObject
App.Visible := True; // ensure we see the app
if App.Execute(CommandLine) then
Result := App.ExitCode = 0 // app executed OK � check its exit code
else
Result := False; // app didn't execute
finally
App.Free;
end;
end;
This is a little crude - the TPJConsoleApp class can do a lot better than this. Using code like this isn’t recommended.
One problem with the above code is that, if you run the console app from a GUI application, your GUI locks up until the console app completes.
Try it. Using Delphi, create a new GUI application. First copy the above code for ExecAndWait and ExecAndWait2 into the form unit’s implementation section. Now drop two buttons on the main form and add the following OnClick event handlers:
procedure TForm1.Button1Click(Sender: TObject);
begin
if not ExecAndWait('Timed 3') then // runs Timed.exe for 3 seconds.
ShowMessage('Non-zero error code or application could not be executed');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if not ExecAndWait2('Timed 3') then // runs Timed.exe for 3 seconds.
ShowMessage('Non-zero error code or application could not be executed');
end;
Run the application. Click either button. The console application will run. Try switching back to the application while the console application is running. You can’t can you?
We’ve used an application called
Timed.exe
here that takes a parameter that tells it how many seconds to run. You can use anything suitable. If you want to tryTimed
, its source code is available in Appendix 2.
This behaviour may be what you want, but what if the console app freezes? Your app can’t do anything about it. Example 2 shows how to let your GUI application “breathe” while the console application executes.