Link to home
Start Free TrialLog in
Avatar of Dave_B_C
Dave_B_C

asked on

Calling executables

Is it possible for a Delphi program to call another already compiled .exe delphi program? If so how?
ASKER CERTIFIED SOLUTION
Avatar of Roza
Roza
Flag of Slovenia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of VGR
VGR

I already gave some code for a previous answer, so why not to you ?

Function ExecNewProcess(ProgramName : String; doWait : Boolean = False) : Boolean;
var
  StartInfo  : TStartupInfo;
  ProcInfo   : TProcessInformation;
  CreateOK   : Boolean;
begin
  { fill with known state }
  FillChar(StartInfo,SizeOf(TStartupInfo),#0);
  FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
  StartInfo.cb := SizeOf(TStartupInfo);

  CreateOK := CreateProcess(nil, PChar(ProgramName), nil, nil,False,CREATE_NEW_PROCESS_GROUP+NORMAL_PRIORITY_CLASS,
              nil, nil, StartInfo, ProcInfo);

  { check to see if successful }
  if CreateOK then
    //may or may not be needed. Usually wait for child processes
    if doWait then WaitForSingleObject(ProcInfo.hProcess, INFINITE);
  ExecNewProcess:=CreateOK;
end;

I'm sure you'll know how to use it by looking at the signature (so-called "prototype" by C guys)
for any file not just exe you can do:

uses shellapi;

ShellExecute(Application.Handle, 'open',pchar('c:\windows\somefile.txt), nil, nil, SW_NORMAL);


or for exe and you know the path you can do simply:

WinExec(pchar('c:\windows\notepad.exe'), SW_ShowNormal);
wrong.

From doc for Winexec API :
"Remarks

Win32-based applications should use the CreateProcess function rather than this function. The WinExec function exists in Win32 to provide compatibility with earlier versions of Windows.

For more information about how the WinExec function is implemented, see the Remarks section of the LoadModule function."

Moreover : "In Win32, the WinExec function returns when the started process calls the GetMessage function or a time-out limit is reached", so you can't tell when it's done unless you begin to play with FindWindow() stuff...

Why do you think I made myself pain by using CreateProcess ? ;-)

PS : the ShellExecute idea is also something I definitely use a lot, especially with URIs but, again, it's for the cases where you don't care if the "spawned" executable has finished or not, before continuing the main process.
VGR,

never forget to close the handles you've opened:

if CreateOK then begin
   //may or may not be needed. Usually wait for child processes
  if doWait then WaitForSingleObject(ProcInfo.hProcess, INFINITE);
  CloseHandle(ProcInfo.hProcess);
  CloseHandle(ProcInfo.hThread );
end;

or within try..finally block which I prefer.

There is a ShellExecuteEx API also which allows you to wait for the new process to get finished.

Regards, Geo
yo

unless I'm wrong, this is implicitely done by the disappearance of the scope where ProcInfo is declared 8-)

Anyway, it works like this 8-)

This code comes (adapted) from reliable sources
procedure TForm1.Button1Click(Sender: TObject);
var
 StartUpInfo : TStartUpInfo;
 ProcessInfo : TProcessInformation;
 Command : array [0..512] of Char;
 Success : Boolean;
begin
 StrpCopy (Command,Trim('C:\Windows\Notepad.exe'));
 FillChar(StartUpInfo,SizeOf(StartUpInfo),#0);
 StartUpInfo.wShowWindow:=SW_SHOWNORMAL;
 StartUpinfo.cb:=SizeOf(StartUpInfo);
 StartUpinfo.dwFlags:= STARTF_USESHOWWINDOW;
 Success:= CreateProcess(nil, Command, nil, nil, False,
      CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
      nil, StartUpInfo, ProcessInfo);
end;

*****

You can also change:

StrpCopy (Command,Trim('C:\Windows\Notepad.exe'));

into:

StrpCopy (Command,Trim(Edit1.Text));

then you can define the program which you want to run.
Avatar of Dave_B_C

ASKER

Used one of the routines on this link... worked fine... thanks!