Newsgroup: it.comp.programmare.win32
Titolo: caricare applicazioni esterne

Ciao a tutti.
Ho realizzato un applicazione in Vc++ 6.0. Vorrei fare in modo che su
richiesta caricasse degli eseguibili preesistenti. Esiste un modo per
richiamare dall'interno della mia applicazione questi eseguibili (ad
esempio notepad o un qualsiasi altro eseguibile ottenuto come
applicazione di console) e poi richiuderli?
Grazie a chi mi sapra' aiutare.
Ciao Stefano
-- 
" Catastrofi del nostro secolo: Hiroshima 45, Cernobyl 86, Windows 95. "

 applicazione di console) e poi richiuderli?
Ogni processo e` associato ad un .EXE (e viceversa).  Puoi
dunque "richiamare" altri .EXE solo nel senso di generare
altri processi separati, che eseguano detti altri .EXE.
Hai molti modi per farlo, dalla complicatissima (ma abbastanza
potente) API CreateProcess, alla ricca e non complicatissima
ShellExecuteEx (c'e` anche una variante obsoleta detta
ShellExecute, ma non esiste alcuna buona ragione per usarla).
Ciascuno di questi "modi di farlo" ti permette, in diversi
modi, di controllare le condizioni di partenza della "altra
applicazione", ma non molto di piu` (ricevi una handle di
processo, relativa al processo-figlio che hai cosi` fatto
partire, ma non sono molte ne` molto utili le cose che ci
puoi fare; terminare un altro processo attraverso la sua
handle, ad esempio, e` assolutamente da evitare, salvo casi
di gravissima emergenza, e puo` portare ad instabilita` del
sistema, ecc ecc).
Per controllare altre applicazioni, dialogare fruttuosamente
con esse, ecc ecc, la strada maestra e` il COM e cio` che su
COM si appoggia.  Ma non tutte le applicazioni lo supportano
(ad esempio, Notepad non lo supporta, e neppure un "Hello
World" fatto come applicazione di console senza interesse
alcuno per il COM, l'Automation, ecc ecc).  Ci sono millanta
altri trucchetti, piu` o meno sporchi, che aiutano in vari
casi particolari.  Questi vanno dal relativamente pulito,
come ridirigere le handle di standard input/output per una
applicazione di console (qui il tipico problema sara` che
il buffering che l'applicazione di console probabilmente fa
sul proprio output ti impedisce di sincronizzare la tua
applicazione-pilota con quella di console che vorresti
pilotare); al medio-sporco, come DDE (una vecchia e obsoleta
tecnologia, che si rifiuta purtroppo di morire del tutto ma
e` chiarissimamente "gravemente malata":-); allo sporco
veramente, come simulare azioni di mouse e tastiera, spedire
direttamente messaggi alle finestre altrui, iniettare proprio
codice (una DLL) nell'altrui processo, e via insozzando.
A giudicare dal traffico di domande che si vedono su questo
gruppo, piu` un modo di pilotare un'altra applicazione e`
sporco, fragile, e poco generale, piu` interessa a chi su
questo gruppo pone le proprie domande.  Forse questa strana
distorsione viene dal fatto che pilotare le cose in modo
pulito (COM, Automation, ecc) non provoca sostanziali
problemi, mentre naturalmente i problemi sono sempre di
piu` man mano che aumenta la "sporcizia" dell'approccio
usato.  E poi, apparentemente, c'e` molto interesse per
interagire con applicazioni vetuste, obsolete, mal scritte,
che non prevedono nessun modo di essere "pilotate".  Si
e` visto persino qualcuno chiedere come "pilotare" ("a
cucci e spinte") applicazioni come PkZip o WinZip, quando
esiste la gratuita libreria Zlib liberamente linkabile ai
propri programmi per fare esattamente lo stesso lavoro nel
modo piu` pulito immaginabile.  Mah!
Alex

 Alex
Grazie mille per la tua risposta. Quello che volevo fare era proprio
caricare una piccola applicazione di console (di cui non ho il sorgente
ma solo l'eseguibile) che mi permette di eseguire dei calcoli su uno
specifico file di input. Avevo infatti utilizzato ShellExecute ma ero
solamente riuscito a caricare l'applicazione che a questo punto pero'
perde le informazioni sulla "sua" directory di partenza (dove deve
leggere un file di parametri), nonostante io la inserisca come
lpDirectory . Pensavo quindi esistesse un modo piu' "consono" di
caricare questo tipo di applicazione. Forse basta fissare come dir base
dell'applicazione la dir che mi interessa? Ho provato con CreateProcess
ma non riesco a far aprire l'applicazione (mi ritorna sempre 0...)
perche' probabilmente sbaglio qualche parametro. 
Se hai qualche idea che mi puo' essere utile ti ringrazio fin d'ora,
estendendo l'appello a tutto il ng.
Ciao
Stefano

 lpDirectory . Pensavo quindi esistesse un modo piu' "consono" di
ShellExecute e` una vecchia funzione che esiste solo per compatibilita`,
e ShellExecuteEx la versione corrente, ma sul problema che tu esprimi
non presentano sostanziali differenze.
Non ho mai sentito dire di bug con l'una o con l'altra relativi al
settaggio del directory di default per il processo che viene fatto
partire.  Sospetto dunque che si tratti di un bug tuo.
Suggerimento: scrivi una microscopica applicazione console che altro
non fa che scrivere il proprio directory corrente (ad esempio facendo
l'append su c:\pippo.txt, cosi` sei sicuro di non perdertela).  Prova
a far girare quella con il metodo che preferisci e guarda un po' quale
sia il directory corrente che si trova settato.
In generale, riducendo un bug alle condizioni di massima semplicita`
in cui si riesce ancora a riprodurlo si e` ben oltre la meta` del
processo di diagnosticare (e riparare o aggirare) il bug stesso.
Alex

 Alex
Ho provato con ShellExecuteEx mantenendo la stessa struttura di
basedirectory e il tutto funziona. Penso che il problema,per quanto
riguarda ShellExecute, potesse risiedere nella lunghezza dei nomi delle
directory chiamate ma non ne sono sicuro.
Dato che sei cosi' gentile da rispondermi puntualmente, volevo sapere se
esite un modo per ottenere l'handle del processo chiamato tramite
ShellExecuteEx, in modo da avere la possibilita' di mettere la finestra
stabilmente in primo piano con WS_EX_TOP_MOST. La cosa che piu' mi
interesserebbe, pero', e' sapere se esiste un modo per conoscere quando
una applicazione di console chiamata in questo modo termina il suo
lavoro (rilascia l'handle assegnatogli) in modo da poterne, ad esempio,
caricare i risultati salvati in un file di output, oppure per
visualizzare un AfxMessageBox che mi dica che ha finito il suo lavoro.
Grazie per l'aiuto 


 visualizzare un AfxMessageBox che mi dica che ha finito il suo lavoro.
Sia che usi la mia funzioncina, oppure MsgWaitForSingleObject,
o altro, ricordati di usare un ragionevole timeout (se l'applicazione
che invochi puo` prendere a tuo giudizio non piu` di 10-15 secondi,
lasciagliane 30-35 per stare proprio largo); testando il codice di
ritorno vedrai se l'applicazione figlia e` effettivamente terminata, e
allora tornera` WAIT_OBJECT_0, oppure se hai avuto un timeout
o altri problemi, e potrai segnalare l'errore, magari uccidere il
processo-figlio presumibilmente piantato (o almeno dare al tuo utente
l'opzione di chiederti detta uccisione, con un message-box con piu`
bottoni, tipo Yes/No o altro), ecc ecc.
Alex

 Alex
Grazie! Fenomenale la tua funzioncina!! Sembra che la mia applcazione
ora funzioni correttamente!
Ciao
Stefano