Launching an external executable.

Posted on 1999-01-17
Last Modified: 2010-04-06
Hi experts,

there are several ways to start an external executable from the main program.
I created a 32 Bit main program from which I want to launch another 32 Bit
application. I need a solution which works both under WIN95 and WIN98 and WIN NT.

For this purpose, several FAQ's recommend the usage of:

ShellExecute(Application.MainForm.Handle, 'print', , '', '',

I wanted to try it out, but I don't understand the parameter


Does it represent the external executable to be launched?

Moreover I don't know which unit I will have to include in the
uses clause of my demo program, so that my own unit can find

I simply want to do something like:

procedure TfrmMain.Button1Click(Sender: TObject);
  ShellExecute('notepad.exe c:\autoexec.bat');

What is the correct syntax of this ShellExecute statement with all parameters?
Unfortunately, my collection of FAQ's don't provide me with concrete examples,
so I don't understand how I can use this function.

Do you agree that ShellExecute is really the best way to launch another program?
Or should I rather use alternatives like WinExec,ExecAndWait, ShellExecute, CreateProcess.
What is the correct syntax of WinExec,ExecAndWait, ShellExecute, CreateProcess, if I want
to load my autoexec.bat into notepad.exe with the help of these functions.

BTW: I am meanwhile using Delpi 4.0 , standard edition, if that counts.

With kind regards


Question by:mathes
  • 2
  • 2

Accepted Solution

JimBob091197 earned 30 total points
ID: 1362240

ShellExecute is the best method in Win 95/98/NT to execute any file.  The benefit is that it doesn't have to be an EXE file.  It can be DOC, BMP, etc.

The syntax is:

(To answer your question: you have to include the "ShellApi" unit.)

ShellExecute(Self.Handle, 'open', PChar('C:\Windows\Notepad.exe'), PChar('C:\autoexec.bat'), nil, SW_NORMAL);

I use Self.Handle, where Self is the main form, so this is the same as "Application.MainForm.Handle".  This parameter is the window handle of the calling app that can receive error messages if ShellExecute fails, etc.  You can also use GetDesktopWindow.

Another useful way of starting an app is CreateProcess:

  ProcessInfo: TProcessInformation;
  StartUpInfo: TStartUpInfo;
  ZeroMemory(@StartUpInfo, SizeOf(TStartUpInfo));
  with StartUpInfo do
      cb := SizeOf(TStartUpInfo);
      wShowWindow := SW_SHOWNORMAL;;
  CreateProcess(nil, PChar('C:\Windows\Notepad.exe C:\autoexec.bat'), nil, nil, True, NORMAL_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo);

The benefits of CreateProcess are as follows:

(1)  You can close Notepad politely:

function ThreadWndProc(hWnd: HWND; lParam: LParam): Bool; stdcall;
  // lParam is WM_CLOSE, because that's what we send in when
  // we call EnumThreadWindows (below).
  // Thus, the following will send WM_CLOSE to the window.
  SendMessage(hWnd, lParam, 0, 0);

  // Return True to continue enumeration.
  Result := True;

if not (EnumThreadWindows(ProcessInfo.dwThreadId, @ThreadWndProc, WM_CLOSE)) then
  ShowMessage('EnumThreadWindows failed!');

(2)  You can force Notepad to close (unsaved changes in Notepad are lost):

  TerminateProcess(ProcessInfo.hProcess, 0);

(3)  You can execute Notepad & wait for it to terminate:

  ZeroMemory(@StartUpInfo, SizeOf(TStartUpInfo));
  with StartUpInfo do
      cb := SizeOf(TStartUpInfo);
      wShowWindow := SW_SHOWNORMAL;;
  if (CreateProcess(nil, PChar('C:\Windows\Notepad.exe C:\autoexec.bat'), nil, nil, True, NORMAL_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo)) then
      WaitForSingleObject(ProcessInfo.hProcess, INFINITE);

I usually use ShellExecute because it's pretty simple & can be used on any file (if the file extension is registered).  You can use WinExec, but it's maintained only for compatibility with older versions of Windows.  WinExec will call CreateProcess anyway.

LVL 20

Expert Comment

ID: 1362241
JimBob is completely right. Just one addition. "TerminateProcess" is a quite unclean method of terminating another process. Better would be sending a WM_CLOSE message (like JimBob suggested) if the user may save a changed file or a WM_QUIT message, if the user must not save a changed file.

Regards, Madshi.

Author Comment

ID: 1362242
Dear JimBob,

thank you so far for your help.

Can you please tell me, how I can check the returncode of ShellExecute?
If the returncode is not 0, it is better to display an error message and tell the user what was wrong,
instead of a black screen and leaving the user alone with this problem. Which else values except 0
can ShellExecute return?

And can you please the following lines so that they are accepted  by Delphi 4.0 as
syntactically correct:

WinExec,ExecAndWait, ShellExecute, CreateProcess,

I want to learn the usage of these functions, too. Maybe they are valuable and the best
solution in other situations.

uses ;


WinExec ('notepad.exe c:\autoexec.bat');

uses ;


ExecAndWait ('notepad.exe c:\autoexec.bat');

uses ;


ShellExecute('notepad.exe c:\autoexec.bat');

uses ;


CreateProcess('notepad.exe c:\autoexec.bat');

With kind regards


Expert Comment

ID: 1362243
Hi again

The return values from ShellExecute (as per the Win32 help file) are as follows:

ERROR_FILE_NOT_FOUND      The specified file was not found.
ERROR_PATH_NOT_FOUND      The specified path was not found.
ERROR_BAD_FORMAT          The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).
SE_ERR_ACCESSDENIED       The operating system denied access to the specified file.
SE_ERR_ASSOCINCOMPLETE    The filename association is incomplete or invalid.
SE_ERR_DDEBUSY            The DDE transaction could not be completed because other DDE transactions were being processed.
SE_ERR_DDEFAIL            The DDE transaction failed.
SE_ERR_DDETIMEOUT         The DDE transaction could not be completed because the request timed out.
SE_ERR_DLLNOTFOUND        The specified dynamic-link library was not found.
SE_ERR_FNF                The specified file was not found.
SE_ERR_NOASSOC            There is no application associated with the given filename extension.
SE_ERR_OOM                There was not enough memory to complete the operation.
SE_ERR_PNF                The specified path was not found.
SE_ERR_SHARE              A sharing violation occurred.

As for your other questions, I have already given examples of ShellExecute (which "uses ShellApi") and CreateProcess (which "uses Windows), but here is an example for WinExec:

WinExec('C:\Windows\Notepad.exe C:\autoexec.bat', SW_NORMAL);

According to the help file, WinExec returns the following values:
  If the function succeeds, the return value is greater than 31.
  If the function fails, the return value is one of the following error values:
    0 = The system is out of memory or resources.
    ERROR_BAD_FORMAT = The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).
    ERROR_FILE_NOT_FOUND = The specified file was not found.
    ERROR_PATH_NOT_FOUND = The specified path was not found.

(I have never used ExecAndWait, but I suspect it is the Windows 3.1 equivalent to the CreateProcess sample I gave previously - the one where you wait for Notepad to terminate.
Similarly, WinExec is (according to the Help file) "provided for compatibility with earlier versions of Windows. For Win32-based applications, use the CreateProcess function".)

As I said before, I nearly always use ShellExecute.  I sometimes use CreateProcess if I want a little more control over the process.



Author Comment

ID: 1362244
Thank you for your help. This is exactly what I was looking for.

With kind regards


Featured Post

Active Directory Webinar

We all know we need to protect and secure our privileges, but where to start? Join Experts Exchange and ManageEngine on Tuesday, April 11, 2017 10:00 AM PDT to learn how to track and secure privileged users in Active Directory.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Find and Replace Stream with 0s 8 69
JAudiorecorder record freezing the app 29 76
Firemonkey DbLookupComboBox equivalent ? 2 56
Multi-layered image in FireMonkey 9 49
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit If you want to manage em…

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question