Newsgroup: it.comp.programmare.win32
Titolo: come chiudere applicazione aperta con il comando shell

come chiudere applicazione aperta con il comando shell

 writes:
D> come chiudere applicazione aperta con il comando shell
Acida. In windows non esiste come in altri S.O. il modo di uccidere in
modo pulito un processo.
Nel tuo caso  devi o trovare una finestra che sia  gestita dal task da
eliminare, mandargli un VMQuit e sperare che il programma ti dia retta
oppure usare la TerminateThread() che  comunque è una chiamata da fare
solo  quando si  è sicuri  che non  si è  in grado  di far  esegure al
processo una ExitProcess().
+----------------------------------------------------------------+
| Gian Uberto Lauri * "So, are you working on fixing that bug    |
| 
sa...@eng.it
      *  *now* or leaving it until later ?" - YES  |
+----------------------------------------------------------------+
| Attenzione: rispondo ad ogni invio di pubblicità non richiesta | 
| o spam di qualsiasi altro genere con un messaggio al provider  |
| di competenza. Ai sensi della legge sulla privacy NON avete il |
| permesso di utilizzare i miei dati per questi scopi.           |
+----------------------------------------------------------------+

 writes:
GUL> Nel tuo caso  devi o trovare una finestra che sia  gestita dal task da
GUL> eliminare, mandargli un VMQuit e sperare che il programma ti dia retta
GUL> oppure usare la TerminateThread() che  comunque è una chiamata da fare
GUL> solo  quando si  è sicuri  che non  si è  in grado  di far  esegure al
GUL> processo una ExitProcess().
A questo post mi è stato risposto per posta con un messaggio con scudi
antispam  troppo   forti,  in  cui   mi  si  pregava  di   non  citare
EnumerateWindow() come  soluzione. La mia risposta (che  non ho potuto
far pervenire per e-mail) è:
"Non credo che EnumWindows() o  FindWindows() non vadano bene. E' solo
 una operazione lunga, devi prendere  tutte gli handle e per ogni devi
 chiamare  GetWindowThreadProcessId() per  vedere  se il  thread ID  è
 quello - sperando che la Shell()  di VB non restituisca il process ID
 e  la  getWindowThreadProcessID() quello  del  thread principale  :).
 Magari si potesse fare una kill(pid,SIGKILL);..."
Devo aggiungere che questa  tecnica (non testata, ho risposto leggendo
gli  help :))  non funziona  se il  processo da  terminare non  ha una
"pompa dei messaggi" attiva...



non funziona per ovvi motivi la caption della finestra puo cambiare nome ed
ci si ritrova nell'impossibilità di trovarla :)))

> 
A> non funziona per ovvi motivi la caption della finestra puo cambiare nome ed
A> ci si ritrova nell'impossibilità di trovarla :)))
Tu puoi passare a setaccio TUTTE  le finestre aperte e se leggi meglio
il testo  sopra parlo di handle,  processID e mai di  caption. O pensi
che sia così imbecille da non aver capito che era la variabilità della
caption a spaventarti ?
/* Esempio non provato, ma a naso funziona. Tradurselo da soli in VB */
WNDENUMPROC foo(HWND bar, LPARAM foobar)
{
    DWORD task;
    DWORD thread;
    thread = GetWindowThreadProcessId(bar, &task);
    /*
     * savedtask è l'id ritornato da shell
     */
    if(task == savedtask)
	DestroyWindow(bar);
}
E poi fai la chiamata 
	EnumWindows(foo,0);
Do I make sense ?



veramente non ero io ma davide a porre la domanda cmq la mia precisazione
non voleva essere un'offesa ma solo un modo per chiarire visto che ero
interessato anch'io alla cosa ....
Comunque così a naso guardavo la tua funzione che forse ha un errore ma
magari hai informazioni più esatte
WNDENUMPROC foo(HWND bar, LPARAM foobar)
{
    DWORD task;
    DWORD thread;
    thread = GetWindowThreadProcessId(bar, &task);
il task devi ricavarlo da "LPARAM foobar" parametri se non erro
....giusto???
è solo una precisazione magari puo essere utile

 writes:
A> veramente non ero io ma davide a porre la domanda cmq la mia precisazione
A> non voleva essere un'offesa ma solo un modo per chiarire visto che ero
A> interessato anch'io alla cosa ....
O.K.! Scusa per la risposta a pallettoni !
A> Comunque così a naso guardavo la tua funzione che forse ha un errore ma
A> magari hai informazioni più esatte
A> WNDENUMPROC foo(HWND bar, LPARAM foobar)
A> {
A>     DWORD task;
A>     DWORD thread;
A>     thread = GetWindowThreadProcessId(bar, &task);
A> il task devi ricavarlo da "LPARAM foobar" parametri se non erro
A> ....giusto???
A> è solo una precisazione magari puo essere utile
No. LPARAM foobar (foobar == fubar == Fucked Up Beyond Any Recovery) è
un  parametro che  è messo  per compatibilità  (ma serve  a  nulla) in
quanto EnumWindows() per flessibilità  ha previsto un parametro utente
dal passare alla funzione  lpEnumFunc() di cui ha ricevuto l'indirizzo
iniziale (puntatore a) come primo parametr.
Quindi  EnumWindows non  fa  altro che  andare  a caccia  di TUTTE  le
finestre aperte  di livello più alto  (Dialog, SDI, MDI  Parent) e per
ognuna  di  queste   richiama  lpEnumFunc()  passando  come  parametri
l'handle della finestra in esame ed il parametro utente.
La mia foo() non ha  alcun bisogno del parametro utente[*], basta solo
lo handle.   L'ID del processo  da terminare è passato  come variabile
globale (le variabili  globali sono mostly harmless in  un sistema con
indirizzamento a 32 bit... Basta usarle con intelligenza). In VB credo
sia una scelta molto comoda, ed anche in C non rompe le scatole.
[*] volendo  si può chiamare EnumWindows() passaondo  come lParam l'ID
del processo da terminare, in quanto hanno la stessa dimensione.
In questo caso foo() diventa
/*
 * Foobar contiene l'id del task da terminare
 */
WNDENUMPROC foo(HWND bar, LPARAM foobar)
{
     DWORD task;
     DWORD thread;
     thread = GetWindowThreadProcessId(bar, &task);
     if((HANDLE) foobar == task)
	/* Si spera che la distruzione della finestra 
	   causi una ExitProcess */
	DestroyWindow(hwnd);
}
e la chiamata a EnumWindows() avviene in un contesto del genere:
....
/* avviamo il processo */
CreateProcess( lpApplicationName,
               lpCommandLine,
               lpProcessAttributes,
               lpThreadAttributes,
               bInheritHandles,
               dwCreationFlags,
               lpEnvironment,
               lpCurrentDirectory,
               lpStartupInfo,
               lpProcessInformation);
....
/* facciamo terminare il processo */
EnumWindow(foo,(LPARAM) lpProcessInformation.dwProcessId);
...
Per chi dovesse usare VB, Shell ritorna il process ID, quindi si
avrebbe una situazione
	Dim processo As Long
....
	processo = Shell("programma")
....
	EnumWindow foo, processo
.....


eliminare, mandargli un VMQuit 
VMQuit ? :) forse WM_QUIT.
Comunque, non e' questo il messaggio da spedire, ma WM_CLOSE.
WM_QUIT e' un messaggio interno al ciclo di elaborazione di messaggi
del thread.
--
Andrea Laforgia (ICQ 87230455)
------------------------------ 
#exclude <windows.h>

 Magari si potesse fare una kill(pid,SIGKILL);..."
Si puo'.
TerminateProcess()
Con il Resource Kit di WindowsNT e' compresa l'utility "kill".
In via alternativa esiste anche "pskill" (
www.sysinternals.com
) che
riesce ad uccidere anche in remoto.


> Magari si potesse fare una kill(pid,SIGKILL);..."
AL> Si puo'.
AL> TerminateProcess()
Vero, ottieni qualcosa di molto  simile. Solo che mentre sotto Unix la
cosa  è  ritenuta  molto  sicura   (non  so  se  le  shared  libraries
introducono rogne), sotto Windows è ritenuta insicura.
Mi spiego comunque meglio :
	Come sarebbe bello avere un segnale asincrono che porti
	immediatamente il codice su un epilogo pulito.
:)


	immediatamente il codice su un epilogo pulito.
Sotto Windows purtroppo non e' possibile.
TerminateProcess e' da usare con cautela, perche' rimangono "appese"
le DLL "attaccate" all'applicazione ... ! :(
