Newsgroup: it.comp.lang.c++
Titolo: _wspawnlp (piccolo dubbio....)

Ciao a tutti,
volevo una piccola informazione riguardo questa funzione (o una analoga, se
esiste, che non sia _exec??,..).
Ho bisogno di richiamere un programma esterno (il pkunzip) e poichè devo
rientrare nel programma principale utilizzo questa funzione.
Il "problema" è questo: c'è un modo per far eseguire questo programma senza
che sia visualizzata la sua finestra? Mi spiego meglio, preferirei che
quando il mio programma richiama il pkunzip non ci fosse il cambio di
modalità video(Win95-> Emulazione dos..)
Probabilmente sarebbe sufficiente eseguire il tutto ridotto a icona, ma non
ho trovato nessun parametro che mi permetta di fare ciò.
Grazie,
Francesco Aruta

che sia visualizzata la sua finestra? Mi spiego meglio, preferirei che
Certamente...:
    STARTUPINFO sui;
    memset(&sui, 0, sizeof(sui));
    sui.cb = sizeof(sui);
    sui.dwFlags = STARTF_USESHOWWINDOW;
    sui.wShowWindow = SW_HIDE;
    PROCESS_INFORMATION pi;
    BOOL rc = CreateProcess("c:\\dove\\sta\\altroprog\\ap.exe",
        "ap c:\\fap1.txt c:\\fap2.txt", 0, 0, 0, 0, 0, 0, &sui, &pi);
    if(!rc)
        // errore di esecuzione, v. GetLastError
Qui, come si vede da tutti quegli zeri, stiamo usando i
default praticamente per tutti i parametri di CreateProcess,
con l'eccezione della STARTUPINFO -- e, anche per
quella, usiamo solo il parametro di "show window".  Con
esso, possiamo specificare qualsiasi modalita` per la
prima visualizzazione della finestra del nuovo processo,
dal "nascosta" come imponiamo qui, a "tutto-schermo"
come chiederemmo con SW_SHOWMAXIMIZED
(naturalmente, occorre che il processo figlio rispetti
questo parametro quando crea la propria window, ma
tutti i programmi ben scritti lo fanno; e in particolare, per
programmi di console, la window [console] e` mostrata
dal sistema, che processa correttamente il parametro).
Alex


Grazie mille ancora una volta...
Solo un piccolo dubbio(per la cronaca, non ho utilizzato ancora la "nuova"
funzione) la funzione da me specificata utilizzava la variabile ambiente
PATH per "trovarsi" il programma... Esiste una cosa analoga con questa,
oppure devo specificare comunque la directory in cui risiede il programma?
AriGrazie..
Francesco Aruta

ho trovato nessun parametro che mi permetta di fare ciò.
ShellExecute, CreateProcess, WinExec, permettono tutte di specificare
lo stato della finestra del programma che verra lanciato, l'unico
dubbio che ho e' se funziona anche con i programmi console.
Gianpaolo Bottin
- Live Long and Prosper -

oppure devo specificare comunque la directory in cui risiede il programma?
Anche CreateProcess supporta la PATH (cosa non necessariamente prudente,
ma, tant'e`...!).  Precisamente, se il filename che dai per l'eseguibile
da far partire non comprende un directory, l'ordine di ricerca e`:
1. il directory da cui e` stata originalmente caricata l'EXE che
   sta girando;
2. il current-directory del processo;
3. il system directory (quello che ti restituisce GetSystemDirectory;
   in subordine, su NT, il 16-bit system directory);
4. il windows directory (quello che ti restituisce GetWindowsDirectory)
5. i directory elencati nella variabile d'ambiente PATH nell'ordine
   in cui essi sono elencati
Tutto questo si applica alla possibilita` di specificare l'eseguibile
come inizio del *secondo* parametro, la "command line" (l'unica che
funziona sempre, cioe` anche su NT per programmi a 16 bit); se invece
specifichi l'eseguibile come *primo* parametro, tutta questa ricerca
non ha luogo -- si usano solo il drive corrente e il directory corrente
del processo (almeno, cosi` dice la documentazione -- ho osservato
diversi comportamenti in diversi sistemi basati su Win32, cioe` i
vari release di NT, 95, 98, e Win32s).
Alex
--
 ____    Alex Martelli, Bologna, Italia -- email: 
al...@magenta.com
 \SM/___                                 
http://magenta.com/~alex
  \/\bi/     You never know what is enough unless you know what
     \/          is more than enough.

Solo  una piccola precisazione...
SW_HIDE dovrebbe(da quanto ho capito io) ridurre a icona l' applicazione
chiamante il processo non il contrario (come servirebbe a me...)  o no?
Era cosě giusto per essere sicuri...
Ciao, e grazie ancora,
Francesco Aruta
P.S. Ho risolto utilizzando SW_MINIMIZE, anche se ora ho il problema di
interrompere l' esecuzione della finestra principale fino a quando il
pkunzip non ha finito...

pkunzip non ha finito...
CreateProcess, se ha successo, ti riempie una struttura di tipo
PROCESS_INFORMATION il cui indirizzo tu passi nella chiamata.
Un campo della struttura PROCESS_INFORMATION si chiama hProcess
e contiene la handle del process che hai appena creato.
La chiamata WaitForSingleObject prende due argomenti:
    -- la handle su cui aspettare,
    -- l'intervallo di timeout in millisecondi (INFINITE se non
       vuoi mai uscire per timeout)
e ti ritorna WAIT_OBJECT_0 se l'handle su cui aspetti viene
"segnalata", ovvero WAIT_TIMEOUT se il timeout e` scaduto.
La handle di un processo viene "segnalata" quando il processo
termina.
Quindi, riassumendo:
	PROCESS_INFORMATION pi;
	if(!CreateProces( ... ,&pi)) {
	    // diagnostica l'errore
	    // e termina
	} else {
	    WaitForSingleObject(pi.hProcess,INFINITE);
	}
e` un modo di far partire un processo e aspettare, senza limiti
temporali, che esso termini.
Non e` la mossa piu` consigliabile se il processo che fai
partire puo` impiegare molto tempo, perche` in questo modo
anche il processo-genitore potrebbe restare bloccato per
la stessa durata temporale.  Se non altro, vogliamo, di
solito, che il processo-genitore risponda ai messaggi Window
durante l'esecuzione del processo-figlio.  Questo si
ottiene ponendo, invece della WaitForSingleObject, una
chiamata alla MsgWaitForMultipleObjects, ad esempio:
	} else {
	    for(;;) {
		// servi i messaggi Windows in coda con un
		// loop di PeekMessage/Translate/Dispatch, poi:
		DWORD dw = MsgWaitForMultipleObjects(
		    1, &pi.hProcess, 0, INFINITE, QS_ALLINPUT);
		if(dw == WAIT_OBJECT_0) break;
	    }
	}
Naturalmente, il "servire" certi messaggi in questo tipo
di situazione puo` anche semplicemente significare scartarli
con un beep (almeno non restano in coda per venire eseguiti
a sorpresa tutti quanti alla fine...:-), ma almeno WM_PAINT
(per il normale repaint se la tua finestra viene coperta poi
scoperta), e i messaggi che indicano che l'utente s'e` rotto
e vuole terminare la tua applicazione, e` meglio servirli
per davvero se non vuoi farti detestare dal tuo utente...
(Attenzione a porre il loop di PeekMessage/Translate/Dispatch
*prima* dell'attesa, perche` quest'ultima si sveglia solo
se *arrivano* messaggi, NON per il semplice fatto che ce
ne sono gia` in coda...!  Questo lascia una minuscola, ma
spiacevole, "condizione di corsa" [rimuovibile usando un
timeout ragionevole, tipo 200 millisecondi, invece di INFINITE,
ma solo a prezzo di un piccolo spreco di tempo di CPU]).



Bhè ovviamente prima ci ho provato e poi ho "postato" la precisazione ;-)...
l'effetto è che mi crea una finestra (quella del pkunzip) a schermo
intero... chiusa la quale mi ripristina il mio programma...
Poi nell' help in linea c'è scritto:
SW_HIDE  Hides the window and activates another window
Ovvero (il Vc++ non lo conosco bene ma un pò d' inglese lo capisco)
"Nasconde la finestra e  ne attiva un'altra"
Quindi o interpreto male l'inglese oppure ho ragione..
Va bè... Aspetto la contro-risposta che la questione mi intriga...
Ciao  (e grazie....sto diventando monotono)
Francesco

Quindi o interpreto male l'inglese oppure ho ragione..
No, hai semplicemente frainteso il contesto -- stai guardando
la documentazione di ShowWindow senza tenere conto che li`
arrivi da CreateProcess attraverso STARTUPINFO.
Ripeto il frammento che ho gia` postato il 31 maggio, appena
modificato per semplicita` e con un paio di info in piu`:
    STARTUPINFO sui;
    memset(&sui, 0, sizeof(sui));
    sui.cb = sizeof(sui);
    sui.dwFlags = STARTF_USESHOWWINDOW;
    sui.wShowWindow = SW_HIDE;
    PROCESS_INFORMATION pi;
    BOOL rc = CreateProcess(0, 
	 "pkunzip -d c:\\pippo\\lo.zip",
         0, 0, 0, 0, 0, 
	 "c:\\pluto", &sui, &pi);
    if(!rc) {
        // errore di esecuzione, v. GetLastError();
        // diagnostica l'errore ed esci -- esempio in MFC:
	DWORD dw = GetLastError();
	CString mesg;
	mesg.Format("Errore %d", dw);
	MessageBox(mesg);
	return;
	// o altri metodi diagnostici piu` raffinati...!
    }
    WaitForSingleObject(pi.hProcess, INFINITE);
    // o altri metodi di attesa piu` raffinati
    // come da mio precedente messaggio
E` questo, piu` o meno, il codice che stai eseguendo nelle tue
prove?  O, se no, che altro?
Prova magari questo "snippet" (agevolmente connettibile a
un bottone qualsiasi di un dialogo qualsiasi, con l'opportuno
cambiamento nelle stringhe in gioco) e facci sapere come ti
funziona.


funziona.
Spiccicato.....
E' esattamente il codice che sto utilizzando (eccezion fatta per il
terzultimo parametro che ho impostato a NULL...)
Adesso ho appena ricompilato Copiano e incollando sul vecchio codice questo
pezzo e il risultato è ( un attimo che linka....) Niente,
continua a mandare a schermo intero il pkunzip...
Questa, nel caso ti interressasse, è la funzione incriminata...
void CDlgPrg::Unzippa(CString Param1, CString Param2)
 // param1 e due ovviamente sono i tuo c:\pippo.zip c:\pluto
{
    STARTUPINFO sui;
    memset(&sui, 0, sizeof(sui));
    sui.cb = sizeof(sui);
    sui.dwFlags = STARTF_USESHOWWINDOW;
    sui.wShowWindow = SW_HIDE ;
    PROCESS_INFORMATION pi;
 char Parametro[255];
 strcpy(Parametro,"pkunzip.exe -o ");
 strcat(Parametro,Param1);
 strcat(Parametro," ");
strcat(Parametro,Param2);
 m_Status.SetText("Aiu is now running pkunzip.exe",0,0);
 BOOL rc=CreateProcess(NULL,Parametro, 0, 0, 0, 0, 0, 0, &sui, &pi);
    if(!rc)
 {
  AfxMessageBox("Error executing pkunzip.exe");
  m_Status.SetText("Error N1010",0,0);
  EndDialog(0);
 }
 else
 {
  WaitForSingleObject(pi.hProcess,INFINITE);
 };
}
Ci sono un paio di cose che non c'entrano nulla (tipo i riferimenti all
barra di stato...) comunque dovrebbe essere piuttosto comprensibile
(nonostante il mio stile pessimo di programmazione.....;-)
Mah che dire? (a parte grazie ovviamente....) spero di non stare rompendo
troppo le *?#?#
Ciao
Francesco Aruta
P.S.  .....fatemi in bocca al lupo che domani ho l'esame di Fondamenti d
'informatica I ( in Turbo pascal... Spero che non mi salti in mente di fare
l' overloading di qualche funzione... eh eh )

continua a mandare a schermo intero il pkunzip...
Inspiegabile... non ho un Win95 sotto mano per provare
(solo Win98 e NT vari), ma non capisco la causa di cio`.
Prova, magari, a isolare questa sola funzionalita` in una
applicazione per il resto minuscola e scheletrica -- se
cosi` funziona correttamente, allora dev'essere qualcosa
d'altro che fai a causare il problema (ma non saprei bene
cosa...), mentre se il problema "si riproduce in piccolo"
allora siamo messi meglio per l'identificazione via debug
delle sue cause.
Alex