Visual Basic Simple
Aprire e chiudere un programma eseguibile
(terza parte)
Sincronizza Indice
Sincronizza Indice
Scarica il progetto
Scarica il progetto
Scarica il testo dell'articolo
Testo dell'articolo
Stampa l'articolo
Stampa l'articolo
Ricerca personalizzata

Difficoltà: 5 / 5

<< Continua dalla parte 2

Studiate le funzioni generiche possiamo vedere la loro applicazione sul codice relativo all'interfaccia

  1. Private Sub PulsanteApri_Click()
  2.   Call CloseAllHandle
  3.   If ApriApp(NomeProgramma.Text) Then
  4.     LabelStato.Caption = "Applicazione aperta"
  5.   Else
  6.     LabelStato.Caption = "Fallita apertura dell'applicazione"
  7.   End If
  8. End Sub

Il click sopra il pulsante Apri richiede l'apertura di un nuovo processo.
Prima di fare questo però richiamiamo la funzione CloseAllHandle per chiudere tutti gli handle lasciati eventualmente aperti da un precedente utilizzo della funzione di apertura di un processo.

Alla riga 134 viene avviato il processo passando alla funzione ApriApp il percorso presente nella casella di testo NomeProgramma.
In base al risultato della funzione, modifica il contenuto della Caption di LabelStato, segnalando un'avvenuta apertura oppure un errore di apertura (righe 134-137).

  1. Private Sub PulsanteChiudi_Click()
  2.   Dim Esito As VbMsgBoxResult
  3.   LabelStato.Caption = "Applicazione in chiusura, attendere"
  4.   If ChiudiApp(False) Then
  5.     LabelStato.Caption = "Applicazione chiusa"

Il click sopra il pulsante Chiudi deve ovviamente produrre la chiusura del processo lanciato medianta l'altro pulsante.

Alla riga 142 dichiariamo una variabile di nome Esito e di tipo VbMsgBoxResult. Tale tipo è un'enumerazione dei valori che può assumere una MsgBox. Essa servirà per chiedere all'utente l'eventuale terminazione del processo.

Alla riga 144 viene effettata la chiusura dell'applicazione in maniera semplice, richiamando la funzione ChiudiApp con il parametro di terminazione impostato a False. Se il risultato dell'operazione di chiusura è True, l'applicazione è stata chiusa e verrà descritta la chiusura nella Label LabelStato (riga 145).

  1.   Else
  2.     Esito = MsgBox("L'applicazione non si chiude terminarla?", vbYesNo)
  3.     If Esito = vbYes Then
  4.       If ChiudiApp(True) Then
  5.         LabelStato.Caption = "Applicazione terminata"
  6.       Else
  7.         LabelStato.Caption = "Terminazione applicazione fallita"
  8.       End If
  9.     Else
  10.       LabelStato.Caption = "Applicazione non chiusa"
  11.     End If
  12.   End If
  13. End Sub

Se invece l'operazione di chiusura semplice non è andata a buon fine, la funzione ChiudiApp restituirà il valore False. Sarà pertanto necessario chiedere all'utente se terminare il processo in maniera forzata.

Alla riga 147 viene mostrata una finestra con la richiesta di terminazione. Il risultato della richiesta sarà memorizzato nella variabile Esito. Se l'utente avrà risposto SI (riga 149) sarà effettuata la chiamta alla funzione ChiudiApp con il parametro di terminazione impostato a True (riga 149). In base al risultato di tale chiamata sarà mostrata una Label differente.

Se invece, l'utente avesse risposto NO alla richiesta di terminazione (riga 154-155), essa non sarebbe avvenuta ed il processo sarebbe stato lasciato aperto. Anche il tal caso sarebbe stata mostrata una Label adeguata.

Prima di vedere l'applicazione di questo codice vediamo una cosina semplice semplice:

  1. Private Sub Form_Unload(Cancel As Integer)
  2.   Call CloseAllHandle
  3. End Sub

Supponiamo di aver lanciato un processo esterno mediante il nostro programma e, lasciando il processo avviato, chiudiamo il nostro programma. È buona regola ricordarsi di liberare gli handle mediante richiamo alla funzione CloseAllHandle.
Possiamo adesso passare alla prova del nostro programma.

Figura 2Lanciamolo ed avviamo il richiamo del programma Calc.exe ovvero la calcolatrice di Windows. Se essa è stata effettivamente installata nel computer la vedremo in primo piano e la LabelStato mostrerà il testo "Applicazione aperta". Se provassimo a chiuderla, essa si chiuderà in maniera del tutto immediata, poiché non ci sono possibilità di blocco, come finestre aperte o richieste di salvataggio.

Proviamo invece a lanciare un altro programma, come il Blocco Note di Windows. Il nome del file è Notepad.exe. Lanciato questo scriviamo qualcosa e proviamo a chiudere il programma mediante il pulsante Chiudi del nostro progetto.

Figura 3Sarà richiesto di salvare il testo digitato. Rispondendo Si il testo verrà salvato ed il programma si chiuderà regolarmente. Se si risponderà No il testo non verrà salvato ed il programma si chiuderà regolarmente.
Rispondendo, invece, Annulla la chiusura del programma sarà annullata, ma niente verrà comunicato al nostro progetto. Esso attenderà qualche secondo dopo la risposta e se il processo continuerà ad essere eseguito, sarà mostrata una richiesta di terminazione.

Figura 4Se l'utente risponderà NO alla richiesta di terminazione il programma rimarrà aperto. Se invece risponderà SI sarà ritentata la chiusura semplice e se neanche in questo caso il processo si chiuderà (perché l'utente continua a rispondere Annulla oppure il programa è bloccato) verrà terminato senza ulteriori richieste. Tutti i dati non salvati saranno persi.

Figura 5L'utente verrà anche informato che il processo è stato terminato (non chiuso regolarmente) mediante la solita visione della LabelStato.

Prima di chiudere il discorso, vediamo cosa succede se avviamo il processo del WordPad di Windows: il nome del file è Write.exe. Digitiamolo e premiamo il pulsante Apri programma. Esso verrà aperto. Proviamo a chiuderlo mediante il nostro progetto. Vedremo che la LabelStato ci avvertirà della chiusura, ma la finestra continuerà ad esistere.

Questo perché il programma WordPad si compone di due parti. Infatti il vero processo che mostra la finestra non è il Write.exe. Esso è soltanto un launcher (un progetto del genere è presente nella sezione Richieste dei lettori) ed è stato mantenuto esclusivamente per compatibilità dei programmi con le versioni di Windows precedenti al Windows 95. Infatti nelle versioni precedenti a Windows 95 il WordPad si chiamava Write.exe ed era contenuto nella cartella di Windows. Da Windows 95 in poi, il vero processo si chiama Wordpad.exe e si trova nella cartella Accessori all'interno della cartella Programmi. Il launcher è soltanto un processo che avvia un altro processo.

Quindi il nostro programma, quando tenterà la chiusura del processo aperto si accorgerà che esso è già chiuso, ma non saprà mai che quello ha avviato un altro processo e non chiuderà pertanto la finestra aperta.

Il codice proposto è parecchio lungo ed in alcuni punti complesso. Per tali motivi è stato scomposto in varie funzioni al fine di semplificarne la lettura.
Tuttavia, anche lo scopo da ottenere è molto complesso. Non potevamo usare la funzione Shell di Visual Basic vista in una Richiesta dei lettori, perché essa ci restituisce solo un dato in ritorno, ma per il nostro scopo ne servivano ben altri.

Inoltre, il dato restituito della funzione Shell è il PID (Process IDentifier) del programma aperto. In Windows i PID vengono riutilizzati non appena sono nuovamente disponibili.

Ad esempio se lanciassimo la Calcolatrice di Windows la funzione Shell ci ritornerà il PID 129. Chiudiamo la Calcolatrice e subito dopo apriamo il Blocco Note, la funzione Shell ci ritorna nuovamente il PID 129, perché esso è stato rilasciato e Windows, ricercando un PID libero ha trovato il 129 disponibile.

Per il nostro scopo servono altri dati che identifichino in maniera più precisa possibile la Window principale del processo, madre di tutti i controlli (anch'essi Window) a disposizione dell'utente. Infatti, la chiusura di una Window errata provoca, oltre la non corretta chiusura del programma, malfunzionamenti o il blocco del sistema.

Per ogni commento, discussione, critica sul programma o soluzione per i suoi limiti presenti scrivete a bepi@adria.it o bepii@libero.it.

Giuseppe Della Bianca
23 Aprile 2001

Scarica il progetto
Scarica il progetto
Scarica il testo dell'articolo
Scarica il testo dell'articolo
Stampa l'articolo
Stampa l'articolo
Torna all'indice degli HowTo