Newsgroup: it.comp.lang.delphi
Titolo: Avviare applicazione terza im maniera invisibile

Ho la necessitï¿œ di utilizzare un programmino client di un fornitore che 
interroga il proprio server sulla disponibilitï¿œ di det. articoli.
Il programma viene chiamato dal mio applicativo e nel complesso funziona 
bene se non fosse che ad ogni avvio si apre una finestra che prende il 
sopravvento sulla mia app in maniera poco elegante.
Io chiamo l'applicazione con questo codice:
function EseguiApp(const OpenAppl: String; const Wait: Boolean;
    const Params: String; const View: Integer): Boolean;
var
   SEI: TShellExecuteInfo;
begin
   Result := False;
   if FileExists(OpenAppl) then
   begin
     FillChar(SEI, SizeOf(SEI), #0);
     SEI.cbSize := SizeOf(SEI);
     if Wait then
       SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
     SEI.lpFile := PChar(OpenAppl);
     SEI.nShow := View;
     SEI.lpParameters := PChar(Params);
     if ShellExecuteEx(@SEI) then
     begin
       if Wait then
         WaitForSingleObject(SEI.hProcess, INFINITE);
       CloseHandle(SEI.hProcess);
       Result := True;
     end;
   end;
end;
Non ha nessuna importanza che imposti la proprietï¿œ SEI.nShow a HIDE (0), 
l'applicazione se ne infischia bellamente e si pone in primo piano.
Avrei inoltre la necessitï¿œ una volta chiamata di forzarne la chiusura, 
visto che la app rimane aperta in attesa di una risposta dell'utente.
Ringrazio per qualsiasi consiglio.
Roberto

 visto che la app rimane aperta in attesa di una risposta dell'utente.
ma se usi ( per curiosit� ) l'api ShowWindow e gli dici di nascondersi (
alla finestra che ti viene in primo piano )
cosa succede ?
Oppure prova a spedire un messaggio tipo WM_CLOSE alla finestra del
programma e vedi se gli interessa
riceverlo....oppure se c'� qualche pulsante di chiusura ( sulla finestra ),
prova a spedire un messaggio a questo
( WM_CLICK ).
Se proprio non si chiude c'� la tanto discussa TerminateProcess.
Secondo me, se ti metti li con un po' di pazienza e l'help Win32SDK sotto
mano, vedrai che ci riesci.
P.S. Ho come l'impressione che mi sto dimenticando di dirti qualcosa a
riguardo, ma forse � solo tardi.
Ti saluto
Antonio

 Antonio
Grazie Antonio, adesso faccio un pï¿œ di prove e ti faccio sapere
Roberto

 (tipo proprietï¿œ StayOnTop delle form di delphi)
Provato. Come volevasi dimostrare non funziona.
Ho due alternative: o quelli che hanno fatto il programma client mi 
dicono come interroga il server in modo che possa farlo io direttamente, 
ma non ci credo tanto perchï¿œ mi svelerebbero i loro sacri segreti (non 
so se ci avete fatto caso ma tra sw house c'ï¿œ un pï¿œ un'atmosfera da muro 
di gomma), o mi accontento di avere una form che non c'entra niente e 
che occasionalmente mi salta fuori davanti alla mia app.

 (tipo proprietà StayOnTop delle form di delphi)
e' una cosa che personalmente detesto...
Se sei in debug, restano li e rompono..
Se non sei in debug e la app va in errore, la cazzo della dialog di
errore sta dietro e non vedi un tubazzo...
Continuo a chiedermi il xche di questa scelta....
Scusate lo sfogo. :-|
A.

 visto che la app rimane aperta in attesa di una risposta dell'utente.
Se hai la necessit� di avere un maggior controllo sull'applicazione che 
lanci, dovresti usare l'API CreateProcess, in particolare la sua struttura
STARTUPINFO. Se non si riesce a nascondere la finestra (secondo me e' 
possibile ma non ricordo come), puoi sempre visualizzarla in una
coordinata 
esterna a quella dei margini del desktop (che � una porcata, lo so, ma in 
fondo, ...)
Ciao
ACSH
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 che occasionalmente mi salta fuori davanti alla mia app.
cio� non si nasconde....vabb�, ma volendo riesci perlomeno a chiuderla ?
WM_CLOSE a quale handle l'hai spedito ?
Fai una FindWindow di quella finestra e guarda se ottieni un handle valido.
Spedici WM_CLOSE e guarda che succede.
Se c'� il pulsante di chiusura, intercetta l'handle di quel pulsante
e mandagli il messaggio appropriato.
Non � detto che risolvi, ma prima di mollare fai un'ultima cosa ( se ancora
non l'hai fatta ).
Avvia Winsight e studiati bene quella maledetta finestra.
Cerca di capire che messaggi entrano in gioco quando la usi.
Ti saluto, in bocca al lupo.
Antonio

 Cerca di capire che messaggi entrano in gioco quando la usi.
Non l'avevo fatto e non  lo sapevo neanche. Idea interessante. Provo subito.
Grazie
Roberto

 ACSH
Ciao e grazie

 subito.
Accidenti il programma che dici tu (WinSight) non si trova piï¿œ sul web.
Esiste un WinSight della Deltek che ï¿œ un Integrated Project Management, 
ma non credo c'entri nulla.
Il programma che riporti tu era di Arthur & Vladimir Nesterovsky ed era 
freeware, ma la pagina del download l'hanno tolta.
Qualcuno gli avrï¿œ comprato il programma. In effetti ï¿œ utile un programma 
che intercetta qualsiasi cosa entra od esca da una finestra.

Roberto Casarini ha scritto:

Neanche CreateProcess va bene.
Evidentemente la form che viene visualizzata non � direttamente 
collegata con il processo che l'ha chiamata (non so come hanno fatto).
Riporto comunque il codice utilizzato per conoscenza:
procedure NuovoProcesso(const Program: string; const Wait: Boolean = False);
var
   StartInfo: TStartupInfo;
   ProcInfo: TProcessInformation;
   CreateOK: Boolean;
   PProgramName: PWideChar;
begin
   FillChar(StartInfo,SizeOf(TStartupInfo),#0);
   FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
   StartInfo.cb := SizeOf(TStartupInfo);
   StartInfo.dwX := 5000; //Posizione assurda per visualizzarla fuori 
dallo schermo
   StartInfo.dwY := 5000; //Posizione assurda per visualizzarla fuori 
dallo schermo
   StartInfo.wShowWindow := SW_HIDE; //Finestra invisibile ma se ne 
infischia
   GetMem(PProgramName, 100);
   try
     StrPCopy(PProgramName, WideString(Program));
     CreateOK :=
       CreateProcess(nil, PProgramName, nil, nil, False,
       CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS,
       nil, nil, StartInfo, ProcInfo);
   finally
     FreeMem(PProgramName);
   end;
   if CreateOK then
   begin
     if Wait then
       WaitForSingleObject(ProcInfo.hProcess, INFINITE);
   end
   else
     ShowMessage('Unable to run '+ProgramName);
   CloseHandle(ProcInfo.hProcess);
   CloseHandle(ProcInfo.hThread);
end;

 Neanche CreateProcess va bene.
Non � del tutto vero. In realt� con il CreateProcess visto che mi 
restituisce l'handle del process posso terminarlo quando voglio con il 
TerminateProcess, quindi uno dei due problemi � risolto.
Mi rimane di rendere invisibile la form generata dal processo chiamato.

 collegata con il processo che l'ha chiamata (non so come hanno fatto).
Non credo che sia possibile. Il caso � probabilmente pi� semplice: la
finestra 
del programma viene creata utilizzando l'API CreateWindow con il flag 
CW_USEDEFAULT non impostato (vedi la documentazione, che lo dice 
esplicitamente) e quindi non si pu� modificarne la posizione.
Io farei una prova impostando il valore di dwFlags a STARTF_USESHOWWINDOW 
prima di assegnare a wShowWindow SW_HIDE.


 prima di assegnare a wShowWindow SW_HIDE.
Provato. Anche cos� niente da fare.
Googlando in giro ho messo su una buona libreria di funzioni per 
controllare processi, thread, e moduli.
Adesso utilizzando in maniera incrociata CreateProcess per avviare il 
processo, che mi restituisce anche l'id dello stesso, e EnumerateWindows 
che mi da l'elenco delle finestre con il processo chiamante riesco ad 
avere l'elenco degli handle delle finestre chiamate dal processo (nel 
mio caso sono 6, ben 6 finestre mi apre il maledetto!).
Pensavo che con l'handle della finestra e la funzione ShowWindows con il 
parametro SW_HIDE riuscissi a nascondere la finestra, ed in effetti 
funziona, solo che se lo chiamo troppo presto non va, probabilmente 
perch� la finestra non � ancora stata istanziata, e se gli metto uno 
sleep ho una finestra che mi si apre per mezzo secondo almeno.
Se alla fine di tutto non avr� risolto nulla, almeno mi sono fatto una 
buona conoscenza di processi (far� l'avvocato).

"Roberto Casarini"  ha scritto nel messaggio

Questa tua procedura, rendendola compilabile e con la 
semplice aggiunta della riga
segnata, a me funziona: l'eseguibile passato come parametro 
si avvia "nascosto".
Provata lanciando IE, un mio programma scritto in VB.net, e 
pure con Notepad.
Non so come aiutarti di pi�.
procedure NuovoProcesso(const ProgramName: string; const 
Wait: Boolean = False);
var
   StartInfo: TStartupInfo;
   ProcInfo: TProcessInformation;
   CreateOK: Boolean;
   PProgramName: PWideChar;
begin
   FillChar(StartInfo,SizeOf(TStartupInfo),#0);
   FillChar(ProcInfo,SizeOf(TProcessInformation),#0);
   StartInfo.cb := SizeOf(TStartupInfo);
   StartInfo.dwX := 5000; //Posizione assurda per 
visualizzarla fuori dallo schermo
   StartInfo.dwY := 5000; //Posizione assurda per 
visualizzarla fuori dallo schermo
   // aggiunta
   StartInfo.dwFlags := STARTF_USESHOWWINDOW;
   StartInfo.wShowWindow := SW_HIDE;
   GetMem(PProgramName, 100);
   try
     StrPCopy(PProgramName, WideString(Programname));
     CreateOK :=
       CreateProcess(nil, PProgramName, nil, nil, False,
       CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS,
       nil, nil, StartInfo, ProcInfo);
   finally
     FreeMem(PProgramName);
   end;
   if CreateOK then
   begin
     if Wait then
       WaitForSingleObject(ProcInfo.hProcess, INFINITE);
   end
   else
     ShowMessage('Unable to run '+ ProgramName);
   CloseHandle(ProcInfo.hProcess);
   CloseHandle(ProcInfo.hThread);
end;
Ciao
ACSH 
--- news://
freenews.netfront.net/
 - complaints: 
ne...@netfront.net
 ---

 Non so come aiutarti di piï¿œ.
Ti ringrazio mi hai dato consigli utili. Per me ï¿œ sufficiente anche 
perchï¿œ ci ho giï¿œ speso troppo tempo.
Ciao
Roebrto