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.exehere that takes a parameter that tells it how many seconds to run. You can use anything suitable. If you want to try
Timed, 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.