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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

932 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now