Running External Programs and System Calls
Sometimes you need to run other programs from your Free Pascal code. For example, you might want to run a command, capture its output, or interact with system tools.
Simple System Calls
To run a command and wait for it to finish:
| program SimpleSystemCall;
{$mode objfpc}{$H+}
uses
Classes,
SysUtils;
begin
WriteLn('Running a system command...');
{ Run the command and wait for it to finish }
ExecuteProcess('notepad', []);
WriteLn('Command finished');
WriteLn('Press enter to exit...');
ReadLn;
end.
|
Running Commands with Arguments
Many commands need arguments (parameters). Here's how to pass them:
| program CommandWithArgs;
{$mode objfpc}{$H+}
uses
Classes,
SysUtils;
begin
WriteLn('Creating a text file...');
{ Run cmd to create a file (Windows) }
ExecuteProcess('cmd.exe', ['/C', 'echo Hello > test.txt']);
WriteLn('File created: test.txt');
WriteLn('Press enter to exit...');
ReadLn;
end.
|
Capturing Command Output
If you want to see what the command outputs, use a different approach:
| program CaptureOutput;
{$mode objfpc}{$H+}{$J-}
uses
Classes,
SysUtils,
Process;
var
Process: TProcess;
StringList: TStringList;
i: integer;
begin
{ Create a process to run a command }
Process := TProcess.Create(nil);
StringList := TStringList.Create;
try
{ Set the command to run }
Process.Executable := 'cmd.exe';
Process.Parameters.Add('/C');
Process.Parameters.Add('dir'); { List files (Windows) }
{ Capture the output }
Process.Options := Process.Options + [poWaitOnExit, poUsePipes];
Process.Execute;
{ Read the output }
StringList.LoadFromStream(Process.Output);
WriteLn('=== Output ===');
for i := 0 to StringList.Count - 1 do
WriteLn(StringList[i]);
finally
Process.Free;
StringList.Free;
end;
WriteLn('');
WriteLn('Press enter to exit...');
ReadLn;
end.
|
Different operating systems have different commands. Use conditional compilation to handle this:
| program CrossPlatform;
{$mode objfpc}{$H+}
uses
Classes,
SysUtils,
Process;
var
Process: TProcess;
Command: string;
Output: TStringList;
begin
Process := TProcess.Create(nil);
Output := TStringList.Create;
try
{ Choose command based on OS }
{$IFDEF WINDOWS}
Command := 'cmd.exe';
Process.Parameters.Add('/C');
Process.Parameters.Add('dir');
{$ENDIF}
{$IFDEF UNIX}
Command := '/bin/ls';
{$ENDIF}
Process.Executable := Command;
Process.Options := Process.Options + [poWaitOnExit, poUsePipes];
Process.Execute;
Output.LoadFromStream(Process.Output);
WriteLn('=== Files in current directory ===');
for var Line in Output do
WriteLn(Line);
finally
Process.Free;
Output.Free;
end;
WriteLn('');
WriteLn('Press enter to exit...');
ReadLn;
end.
|
Getting Exit Codes
Programs return exit codes to tell you if they succeeded or failed:
| program CheckExitCode;
{$mode objfpc}{$H+}
uses
Classes,
SysUtils,
Process;
var
Process: TProcess;
ExitCode: integer;
begin
Process := TProcess.Create(nil);
try
Process.Executable := 'cmd.exe';
Process.Parameters.Add('/C');
Process.Parameters.Add('dir /S /B nonexistent.txt'); { This will fail }
Process.Options := Process.Options + [poWaitOnExit];
Process.Execute;
ExitCode := Process.ExitCode;
WriteLn('Exit code: ', ExitCode);
if ExitCode = 0 then
WriteLn('Command succeeded')
else
WriteLn('Command failed with code: ', ExitCode);
finally
Process.Free;
end;
WriteLn('');
WriteLn('Press enter to exit...');
ReadLn;
end.
|
Running Programs from Your App
You can launch other programs and let them run:
| program LaunchProgram;
{$mode objfpc}{$H+}
uses
Classes,
SysUtils,
Process;
var
Process: TProcess;
begin
Process := TProcess.Create(nil);
try
{ Open a URL in the default browser }
{$IFDEF WINDOWS}
Process.Executable := 'cmd.exe';
Process.Parameters.Add('/C');
Process.Parameters.Add('start https://www.google.com');
{$ENDIF}
{$IFDEF UNIX}
Process.Executable := 'xdg-open';
Process.Parameters.Add('https://www.google.com');
{$ENDIF}
{ Don't wait for the program to finish }
Process.Execute;
WriteLn('Browser opened!');
finally
Process.Free;
end;
WriteLn('Press enter to exit...');
ReadLn;
end.
|
Important Notes
- Exit code 0 usually means success
- Other exit codes mean something went wrong (varies by program)
- Use
poWaitOnExit if you need to wait for the program to finish
- Use
poUsePipes if you want to capture the output
- Always use
try...finally to make sure the process is cleaned up
Common Use Cases
- Getting file information - Run
dir or ls and parse the output
- Running scripts - Execute batch files, shell scripts, or Python scripts
- System administration - Run system commands and check results
- Opening files - Use the default program to open documents
- Converting files - Call conversion tools and track progress
The Process Units
You'll need these units:
uses
Process, { For running external programs }
Classes, { For TStringList and other basics }
SysUtils; { For string functions }
Next Steps
- Try capturing output from different commands
- Create a program that runs another program and processes its output
- Build error checking based on exit codes