PDA

Visualizza la versione completa : [DELPHI] Lanciare programma ed attendere che finisca


LeleFT
27-04-2007, 18:39
Buonasera.

Sto sviluppando un piccolo programmino di utility in Delphi.
Sono alla fine e mi si presenta un piccolo fastidio: questo programma deve avviare dei programmi esterni in sequenza, aspettando che ciascuno di essi termini la sua esecuzione prima di lanciare il successivo.

Io, per far eseguire il programma esterno ho utilizzato la funzione ShellExecute. Il programma viene avviato correttamente, ma l'esecuzione prosegue senza attendere che il programma abbia finito.

Come posso fare per far sì che l'esecuzione del programma Delphi attenda che il programma esterno abbia finito, prima di proseguire? Dalla guida non ho trovato nulla (la funzione, che sostanzialmente effettua una chiamata di sistema, non ritorna nulla).

Posto il codice per capire meglio la situazione:


{ ... Qui effettuo la fusione dei dati ...}
ShellExecute(0, 'open', 'fusione_dati', 'parametri', '', SW_SHOWNORMAL);

{ Qui dovrei attendere che 'fusione_dati' abbia finito il suo lavoro prima di procedere }

if ( condizione ) Then
Begin
{ ... Qui lancio l'Update Procedura ...}
ShellExecute(0, 'open', 'update_procedura', '', '', SW_SHOWNORMAL);
end;

Chi mi sa aiutare?

Se non fosse possibile una gestione di questo tipo tramite ShellExecute, cos'altro potrei utilizzare?


Ciao. :ciauz:

LeleFT
27-04-2007, 18:54
Come non detto... in un sito tedesco ho trovato questa che fa proprio al caso mio:


function ShellExecute_AndWait(Operation, FileName, Parameter, Directory: string;
Show: Word; bWait: Boolean): Longint;
var
bOK: Boolean;
Info: TShellExecuteInfo;
{
****** Parameters ******
Operation:

edit Launches an editor and opens the document for editing.
explore Explores the folder specified by lpFile.
find Initiates a search starting from the specified directory.
open Opens the file, folder specified by the lpFile parameter.
print Prints the document file specified by lpFile.
properties Displays the file or folder's properties.

FileName:

Specifies the name of the file or object on which
ShellExecuteEx will perform the action specified by the lpVerb parameter.

Parameter:

String that contains the application parameters.
The parameters must be separated by spaces.

Directory:

specifies the name of the working directory.
If this member is not specified, the current directory is used as the working directory.

Show:

Flags that specify how an application is to be shown when it is opened.
It can be one of the SW_ values

bWait:

If true, the function waits for the process to terminate
}
begin
FillChar(Info, SizeOf(Info), Chr(0));
Info.cbSize := SizeOf(Info);
Info.fMask := SEE_MASK_NOCLOSEPROCESS;
Info.lpVerb := PChar(Operation);
Info.lpFile := PChar(FileName);
Info.lpParameters := PChar(Parameter);
Info.lpDirectory := PChar(Directory);
Info.nShow := Show;
bOK := Boolean(ShellExecuteEx(@Info));
if bOK then
begin
if bWait then
begin
while
WaitForSingleObject(Info.hProcess, 100) = WAIT_TIMEOUT
do Application.ProcessMessages;
bOK := GetExitCodeProcess(Info.hProcess, DWORD(Result));
end
else
Result := 0;
end;
if not bOK then Result := -1;
end;
La riporto integralmente come l'ha scritta l'autore.

Ciao. :ciauz:

alka
28-04-2007, 14:47
Vedo che hai già trovato una soluzione, quindi arrivo un po' tardi. :)

Ad ogni modo, in generale, basta usare la funzione ShellExecuteEx, che dovrebbe essere già disponibile senza dover manualmente dichiarare una importazione di funzione da DLL poiché definita nella unit ShellAPI; tale funzione ti restituisce l'handle del processo che puoi utilizzare con le funzioni di "wait", oppure anche con la funzione TerminateProcess se desideri "uccidere" l'applicazione esterna. :)

Ciao! :ciauz:

mondobimbi
28-04-2007, 15:51
a chi servisse una soluzione per kylix o in generale in free pascal
eses ...., libc;
var
....
risultatoFork, risultatoAttesa : integer;

begin
...
risultatoFork := fork;
case risultatoFork of
-1 : ; // errore nella creazione del processo figlio
0 : begin
Execvp(mio_programma, @argomenti); // o una delle tante incarnazioni
kill(getpid, SIGTERM);
end
else
begin
RisultatoAttesa := waitpid(RisultatoFork, nil, 0);
// confrontiamo se è proprio il processo figlio che è finito
if RisultatoAttesa <> RisultatoFork then
....; // il risultato figlio è uscito in errore
else ... ; // il controllo è di nuovo al genitore
end; // del case
....
end.

ciao
sergio

Loading