Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Launching an external executable.

Posted on 1999-01-17
Medium Priority
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
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2

Accepted Solution

JimBob091197 earned 120 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

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
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…
This course is ideal for IT System Administrators working with VMware vSphere and its associated products in their company infrastructure. This course teaches you how to install and maintain this virtualization technology to store data, prevent vuln…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
Suggested Courses

721 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