Newsgroup: it.comp.lang.c++
Titolo: Esecuzione esterna

Se voglio, dall'interno di un programma in C++, mandare in esecuzione
un programma .exe esterno, senza passare per il buon vecchio 
statemente 'system', cosa devo fare?

 statemente 'system', cosa devo fare?
Dunque poiche' ho appena affrontato e risolto questo problema (e qui' un
pubblico grazie ai suggerimenti di Gian Paolo BOTTIN ci vuole) cerco di
aiutarti il piu' possibile: allora, dipende da cio' che devi fare col
programma .exe che lanci, lanciarlo e dimenticarsene oppure lanciarlo e
tenerne traccia per controli futuri.
1)Usa SPAWNL. Facile ma adatto se non ti serve sapere nulla del programma
lanciato
int _spawnl( int mode,		//modo di lancio: usando _P_NOWAIT il tuo programma
lancia l'altro e prosegue,
					//usando _P_WAIT il tuo programma aspetta che l'altro sia finito prima
di proseguire.
	 const char *cmdname,	//nome del programma da lanciare
	 const char *arg0,	//primo argomento (ripeti il nome del programma)
	 const char *arg1,	//primo argomento da passare al programma
	 ...				//elenco di argomenti
	 const char *argn,	//ultimo argomento
	 NULL );			//fine della lista di argomenti
Rilascia 0 se va bene il lancio, altrimenti un codice d'errore che puo'
essere
E2BIG:	lista di argomenti piu' grossa di 1024 bytes
EINVAL:	argomento mode non valido
ENOENT:	programma da lanciare non trovato
ENOEXEC:	programma da lanciare non eseguibile o in formato scorretto
ENOMEM:	non c'e' abbastanza memoria per il nuovo processo
esempio: int nErr = _spawnl( _P_NOWAIT, "MyProgram", "MyProgram", "MyArg1",
"MyArg2", NULL);
2) Usa CREATEPROCESS. Meno facile ma rilascia info sul processo chiamato.
BOOL CreateProcess( 
	LPCTSTR lpApplicationName,				// nome dell'eseguibile
	LPTSTR lpCommandLine, 					// linea comando completa 
	LPSECURITY_ATTRIBUTES lpProcessAttributes,	// attributi di sicurezza del
processo
	LPSECURITY_ATTRIBUTES lpThreadAttributes, 	// attributi di sicurezza del
thread
	BOOL bInheritHandles, 					// ereditarieta' dell'handle del processo 
	DWORD dwCreationFlags, 					// flag di creazione 
	LPVOID lpEnvironment, 					// blocco di ambiente 
	LPCTSTR lpCurrentDirectory, 				// nome della directory corrente 
	LPSTARTUPINFO lpStartupInfo, 				// punta a STARTUPINFO 
	LPPROCESS_INFORMATION lpProcessInformation); 	// punta a
PROCESS_INFORMATION 
per maggiori dettagli sui parametri vedi il manuale on line.
io l'ho usata in questa chiamata lascindo a NULL odefault i parametri meno
indispensabili:
PROCESS_INFORMATION processInfo;
memset(&processInfo, 0,sizeof(PROCESS_INFORMATION));
STARTUPINFO	startupInfo;
memset(&startupInfo, 0,sizeof(STARTUPINFO));
startupInfo.cb = sizeof(STARTUPINFO);
BOOL ::CreateProcess( 
		NULL,			// eventuale path (usa command line)
		(LPTSTR) "\\\\MyServer\\MyDisc\\MyDir\\MyProgram MyArg1 MyArg2",	//
command line string completa
		NULL,			// default process security attributes 
		NULL,			// default thread security attributes 
		TRUE, 		// handle inheritance flag 
		CREATE_DEFAULT_ERROR_MODE,	// creation flags 
		NULL, 		// default environment 
		NULL, 		// default current directory 
		&startupInfo,	// STARTUPINFO 
		&processInfo);	// PROCESS_INFORMATION 
ovviamente rilascia TRUE se va a buon fine FALSE in altri casi.
In processInfo ti ritrovi l'handle del processo creato, se ti serve in
altre parti del programma
per verificare per esempio se e' ancora attivo o meno, ricordati in ogni
caso che PRIMA di terminare
il programma chiamante DEVE chiudere l'handle del programma chiamato (o
meglio la sua copia interna).
Spero di esserti stato d'aiuto.
-- 
================
       _/
    _/_/_/
     _/
    _/  _/
    _/_/
tec...@login.it
================

Ho seguito il consiglio di Fabio Banfi (che ringrazio calorosamente)
circa lo statement SPAWNL, ma ottengo sempre come ErrorCode di ritorno
'-1'. Inoltre, il parser mi da come Undeclared le costanti E2BIG,
EINVAL, ENOENT, ENOEXEC e ENOMEM, nonostante io abbia incluso la
libreria 'process.h'. Come mai il programma esterno non mi parte?
Pongo di seguito l'istruzione che ho scritto:
	int nErr = _spawnl(_P_NOWAIT,"scantool", "scantool", NULL);
Ditemi dove ho sbagliato. 'scantool' e' un .exe che si trova nella
stessa dir del programma in C++.
Specifico che sto usando il Visual C++ 4.0 della Microsoft.
Bye
Enrico
(un nanonano a Fabio)

 Specifico che sto usando il Visual C++ 4.0 della Microsoft.
Io uso il VC++5.0 SP2 e da me funziona, ma non penso che dipenda dalla
versione
del VC++.
Fammi sapere.
Fabio


Purtroppo SPAWNL ancora non funziona.
Ho scritto lo statement:
	int nErr = _spawnl(_P_NOWAIT,"C:\\Scantool\\Scantool", 
"C:\\Scantool\\Scantool",                    
NULL);
ma adesso l'errore e' ENOSPC. Dovrebbe voler significare che
il file lo ha trovato ma non ha abbastanza spazio su disco per
eseguirlo. 
Non capisco il senso di questa cosa.
Tra l'altro io ho ben 24 M free.
Bye
Enrico