En esta sección de Código fuente en Delphi vamos a mostrar cómo podemos ejecutar una app externa y esperar a que esta termine su ejecución.
Para ello, he escrito esta pequeña app de ejemplo
Para ejecutar aplicaciones externas disponemos de dos funciones de la Api: CreateProcess y ShellExecuteEx (esta última de la ShellApi)
Para utilizar la función CreateProcess he escrito la "function Ejecutar(const Archivo, Params: string; Mostrar: Word; esperar: boolean): Boolean;"
Los parámetros que recibe esta función son:
La función "Ejecutar" devuelve verdadero/falso según se haya podido realizar correctamente la acción.
Como ya he comentado anteriormente, a esta función debemos pasarle en el parámeto "Archivo" la ruta completa del programa que queramos ejecutar, por ejemplo "C:\windows\system32\notepad.exe" y además debe ser la ruta de un archivo ejecutable (.exe .bat .com ...)
Para utilizar la función ShellExecuteEx he escrito la funció EjecutarShell que tiene exactamente los mismos parámetros que la función explicada anteriormente. En este caso debemos incluir en la clausula "uses" la unidad "shellapi"
La principal ventaja de la función EjecutarShell sobre la función Ejecutar, es que en esta nueva función, el parámetro "Archivo" no es necesario que contenga la ruta completa del archivo ejecutable, puesto que si no lleva ruta, el sistema se encargará de buscarlo. Por ejemplo, no es necesario escribir "C:\windows\system32\notepad.exe" bastará con escribir "notepad.exe" o incluso "notepad" para que se ejecute el block de notas. Es más, este parámetro "Archivo" no es necesario que sea un archivo ejecutable (como ocurría con la función anterior), puede ser un documento o incluso una dirección de internet, que el sistema se encargará de abrir el programa adecuado para mostrar ese documento o página web.
En la siguiente imagen puedes ver un ejemplo de uso de esta app.
A continuación, puedes ver el código completo de la app, y si lo deseas puedes descargarlo todo (código y app) en un archivo "zip".
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Label1: TLabel; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses shellapi; function Ejecutar(const Archivo, Params: string; Mostrar: Word; esperar: boolean): Boolean; var StartupInfo: TStartupInfo; ProcInfo: TProcessInformation; CmdLine: string; begin CmdLine := '"' + Archivo + '" ' + Params; FillChar(StartupInfo, SizeOf(StartupInfo), #0); with StartupInfo do begin cb := SizeOf(StartupInfo); dwFlags := STARTF_USESHOWWINDOW; wShowWindow := Mostrar; end; Result := CreateProcess(nil, PChar(CmdLine), nil, nil, False, CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil, PChar(ExtractFilePath(Archivo)), StartupInfo, ProcInfo); if not Result then exit; if esperar then WaitForSingleObject(ProcInfo.hProcess, INFINITE); CloseHandle(ProcInfo.hProcess); CloseHandle(ProcInfo.hThread); end; procedure TForm1.Button1Click(Sender: TObject); var OK: boolean; begin Hide; OK := Ejecutar('c:\windows\system32\notepad.exe', '', SW_SHOWNORMAL, true); Show; if OK then ShowMessage('Ejecutar realizado con éxito.') else ShowMessage('Error al Ejecutar el programa.'); end; ///////////////////////////////////////////////////////////////////////////////////////// function EjecutarShell(const Archivo, Params: string; Mostrar: Word; esperar: boolean): Boolean; var Info: TShellExecuteInfo; begin FillChar(Info, SizeOf(Info), 0); Info.cbSize := SizeOf(Info); Info.fMask := SEE_MASK_FLAG_NO_UI or SEE_MASK_FLAG_DDEWAIT or SEE_MASK_NOCLOSEPROCESS; Info.lpVerb := PChar('Open'); Info.lpFile := PChar(Archivo); Info.lpParameters := PChar(Params); //Info.lpDirectory := PChar(ExtractFilePath(Archivo)); Info.nShow := Mostrar; Result := ShellExecuteEx(@Info); if not Result then exit; if esperar then WaitForSingleObject(Info.hProcess, INFINITE); CloseHandle(Info.hProcess); end; procedure TForm1.Button2Click(Sender: TObject); var OK: boolean; begin Hide; OK := EjecutarShell('notepad', '', SW_SHOWNORMAL, true); Show; if OK then ShowMessage('EjecutarShell realizado con éxito.') else ShowMessage('Error al Ejecutar el programa.'); end; end.