Come terminare un'applicazione "Correttamente" in Win32

Traduzione articoli Traduzione articoli
Identificativo articolo: 178893 - Visualizza i prodotti a cui si riferisce l?articolo.
Espandi tutto | Chiudi tutto

In questa pagina

Sommario

In un mondo perfetto, il processo di potrebbe richiedere un altro processo, tramite una forma di comunicazione tra processi, chiudere la sessione di lavoro. Tuttavia, se non si dispone di controllo a livello di codice sorgente dell'applicazione che si desidera arrestare, quindi non si dispone questa opzione. Sebbene non esista alcun modo di "pulito" garantito per arrestare un'applicazione in Win32, sono necessari passaggi che č possibile eseguire per garantire che l'applicazione utilizza il metodo migliore per la pulitura delle risorse.

Informazioni

Processi a 32 bit (e processi a 16 bit in Windows 95)

In Win32, il sistema operativo č promette di pulire le risorse di proprietā di un processo quando Arresta. Questo non, tuttavia, significa che il processo ha l'opportunitā di eseguire qualsiasi svuotamenti finali di informazioni da disco, tutte le comunicazioni finale su una connessione remota, né significa che il processo della DLL avranno l'opportunitā per eseguire il proprio codice PROCESS_DETACH. Si tratta di Ecco perché č in genere preferibile evitare l'interruzione di un'applicazione in Windows 95 e Windows NT.

Se č assolutamente necessario arrestare un processo, attenersi alla seguente procedura:
  1. Inviare un WM_CLOSE a tutte le finestre principali intestate il processo che si desidera arrestare. Molte applicazioni Windows rispondono a questo messaggio di arresto.

    Nota : risposta dell'applicazione di console WM_CLOSE dipende č installato o meno un gestore di controllo.

    Utilizzare EnumWindows() per trovare i quadratini per le finestre di destinazione. Nella funzione di callback, verificare se le finestre ID di processo corrisponde il processo da arrestare. Č possibile eseguire questa operazione chiamando GetWindowThreadProcessId(). Una volta stabilita una corrispondenza, č possibile utilizzare PostMessage() o SendMessageTimeout() per registrare il messaggio WM_CLOSE alla finestra.
  2. Utilizzare WaitForSingleObject() di attesa per l'handle del processo. Assicurarsi che l'attesa con un valore di timeout, in quanto sono molte le situazioni in cui il WM_CLOSE verrā non arrestare l'applicazione. Ricordarsi di verificare il timeout sufficiente (con WaitForSingleObject() o con SendMessageTimeout()) affinché un utente possa rispondere a qualsiasi finestra di dialogo finestre che sono stati creati in risposta al messaggio WM_CLOSE.
  3. Se il valore restituito č WAIT_OBJECT_0, quindi viene chiusa stesso verso il basso correttamente. Se il valore restituito č WAIT_TIMEOUT, č necessario utilizzare TerminateProcess() per arrestare l'applicazione.

    Nota : se si utilizza getting3 valore di un ritorno da altri WaitForSingleObject() quindi WAIT_OBJECT_0 o WAIT_TIMEOUT, č possibile utilizzare GetLastError() per determinare la causa.
Attenendosi alla seguente procedura, si assegnare all'applicazione la migliore possibilitā possibile arrestare correttamente (oltre da IPC o l'intervento dell'utente).

Il problema di 16 bit (in Windows NT)

Precedente procedura lavoro per applicazioni a 16 bit in Windows 95, tuttavia, le applicazioni Windows 16 bit funzionano in modo molto diverso.

In Windows NT, tutte le applicazioni di 16 bit vengono eseguite in una macchina DOS virtuale (VDM). Questo VDM viene eseguito come un processo Win32 (NTVDM) in Windows NT. Il processo NTVDM dispone di un ID di processo. Č possibile ottenere un handle per il processo tramite OpenProcess(), come con qualsiasi altro processo Win32. Tuttavia, nessuna delle applicazioni a 16 bit che vengono eseguite nella VDM hanno un ID di processo e pertanto č Impossibile ottenere un handle di processo dal OpenProcess(). Ogni applicazione a 16 bit in una VDM dispone di un handle di attivitā a 16 bit e un thread a 32 bit di esecuzione. Č possibile trovare l'ID di handle e thread tramite una chiamata alla funzione VDMEnumTaskWOWEx(). Per ulteriori informazioni, vedere il seguente articolo della Microsoft Knowledge Base riportato di seguito:
175030How to: enumerazione delle applicazioni in Win32
Il primo e pių semplice, quando si chiude un'applicazione a 16 bit in Windows NT consiste nell'arrestare l'intero processo NTVDM. Procedere attenendosi alla procedura descritta in precedenza. Č sufficiente conoscere l'ID processo del processo NTVDM (vedere la KB articolo 175030 citati sopra per trovare l'ID di un NTVDM). Lo svantaggio di questo approccio č che chiude tutte le applicazioni 16-bit in esecuzione in tale VDM. Se non č l'obiettivo, č necessario eseguire un altro approccio.

Se si desidera arrestare una singola applicazione a 16 bit all'interno di un processo NTVDM, seguito sono riportati i passaggi da eseguire:
  1. Inviare un WM_CLOSE a tutte le finestre principali che appartengono al processo, e aventi lo stesso ID thread proprietario dell'attivitā di 16 bit che si desidera arrestare. Il metodo pių efficace per eseguire questa operazione č utilizzando EnumWindows(). Nella funzione callback, verificare se ID di processo e ID di thread della finestra corrisponde l'attivitā di 16 bit da arrestare. Tenere presente che l'ID del processo sarā l'ID di processo del processo NTVDM in cui l'applicazione a 16 bit č in esecuzione.
  2. Sebbene sia necessario un ID di thread, non si dispone di alcun metodo per attesa la terminazione del processo di 16 bit. Di conseguenza, č necessario attendere un arbitrario periodo di tempo (per consentire che una nuova arresto) e quindi tenta di arrestare l'applicazione comunque. Se l'applicazione č giā arrestato, questa verrā eseguita alcuna operazione. Se non č arrestato, verrā terminare l'applicazione.
  3. Terminare l'applicazione utilizzando una funzione denominata VDMTerminateTaskWOW(), reperibile nel Vdmdbg.dll. Richiede l'ID processo della VDM e il numero di attivitā dell'attivitā a 16 bit.
Questo approccio consente di arrestare una singola applicazione a 16 bit all'interno di una VDM in Windows NT. Tuttavia, Windows a 16 bit non č molto buona alla pulitura delle risorse di un'attivitā terminata e non č il WOWExec in esecuzione nella VDM. Se si sta cercando l'approccio possibile cleanest per terminare un'applicazione a 16 bit in Windows NT, si consiglia di terminare l'intero processo VDM. Nota: Se si avvia un'applicazione a 16 bit che č possibile terminare in un secondo momento, quindi utilizzare il CREATE_SEPARATE_WOW_VDM con CreateProcess().

Codice di esempio

Il codice di esempio implementa le tecniche sopra descritte per applicazioni a 16 bit e 32 bit mediante le due funzioni seguenti: TerminateApp() e Terminate16App(). TerminateApp() accetta un ID di processo a 32 bit e un timeout (in millisecondi). Terminate16App(). Entrambe le funzioni utilizzano il collegamento esplicito alle funzioni DLL in modo che sarā binario compatibile in Windows NT e Windows 95.
   //******************
   //Header
   //******************

   #include <windows.h>

   #define TA_FAILED 0
   #define TA_SUCCESS_CLEAN 1
   #define TA_SUCCESS_KILL 2
   #define TA_SUCCESS_16 3

   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout ) ;
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout );

   //******************
   //Source
   //******************

   #include "TermApp.h"
   #include <vdmdbg.h>

   typedef struct
   {
      DWORD   dwID ;
      DWORD   dwThread ;
   } TERMINFO ;

   // Declare Callback Enum Functions.
   BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;

   BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam ) ;

   /*----------------------------------------------------------------
   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )

   Purpose:
      Shut down a 32-Bit Process (or 16-bit process under Windows 95)

   Parameters:
      dwPID
         Process ID of the process to shut down.

      dwTimeout
         Wait time in milliseconds before shutting down the process.

   Return Value:
      TA_FAILED - If the shutdown failed.
      TA_SUCCESS_CLEAN - If the process was shutdown using WM_CLOSE.
      TA_SUCCESS_KILL - if the process was shut down with
         TerminateProcess().
      NOTE:  See header for these defines.
   ----------------------------------------------------------------*/ 
   DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )
   {
      HANDLE   hProc ;
      DWORD   dwRet ;

      // If we can't open the process with PROCESS_TERMINATE rights,
      // then we give up immediately.
      hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,
         dwPID);

      if(hProc == NULL)
      {
         return TA_FAILED ;
      }

      // TerminateAppEnum() posts WM_CLOSE to all windows whose PID
      // matches your process's.
      EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;

      // Wait on the handle. If it signals, great. If it times out,
      // then you kill it.
      if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)
         dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);
      else
         dwRet = TA_SUCCESS_CLEAN ;

      CloseHandle(hProc) ;

      return dwRet ;
   }

   /*----------------------------------------------------------------
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout )

   Purpose:
      Shut down a Win16 APP.

   Parameters:
      dwPID
         Process ID of the NTVDM in which the 16-bit application is
         running.

      dwThread
         Thread ID of the thread of execution for the 16-bit
         application.

      w16Task
         16-bit task handle for the application.

      dwTimeout
         Wait time in milliseconds before shutting down the task.

   Return Value:
      If successful, returns TA_SUCCESS_16
      If unsuccessful, returns TA_FAILED.
      NOTE:  These values are defined in the header for this
      function.

   NOTE:
      You can get the Win16 task and thread ID through the
      VDMEnumTaskWOW() or the VDMEnumTaskWOWEx() functions.
   ----------------------------------------------------------------*/ 
   DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
                        WORD w16Task, DWORD dwTimeout )
   {
      HINSTANCE      hInstLib ;
      TERMINFO      info ;

      // You will be calling the functions through explicit linking
      // so that this code will be binary compatible across
      // Win32 platforms.
      BOOL (WINAPI *lpfVDMTerminateTaskWOW)(DWORD dwProcessId,
         WORD htask) ;

      hInstLib = LoadLibraryA( "VDMDBG.DLL" ) ;
      if( hInstLib == NULL )
         return TA_FAILED ;

      // Get procedure addresses.
      lpfVDMTerminateTaskWOW = (BOOL (WINAPI *)(DWORD, WORD ))
         GetProcAddress( hInstLib, "VDMTerminateTaskWOW" ) ;

      if( lpfVDMTerminateTaskWOW == NULL )
      {
         FreeLibrary( hInstLib ) ;
         return TA_FAILED ;
      }

      // Post a WM_CLOSE to all windows that match the ID and the
      // thread.
      info.dwID = dwPID ;
      info.dwThread = dwThread ;
      EnumWindows((WNDENUMPROC)Terminate16AppEnum, (LPARAM) &info) ;

      // Wait.
      Sleep( dwTimeout ) ;

      // Then terminate.
      lpfVDMTerminateTaskWOW(dwPID, w16Task) ;

      FreeLibrary( hInstLib ) ;
      return TA_SUCCESS_16 ;
   }

   BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam )
   {
      DWORD dwID ;

      GetWindowThreadProcessId(hwnd, &dwID) ;

      if(dwID == (DWORD)lParam)
      {
         PostMessage(hwnd, WM_CLOSE, 0, 0) ;
      }

      return TRUE ;
   }

   BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam )
   {
      DWORD      dwID ;
      DWORD      dwThread ;
      TERMINFO   *termInfo ;

      termInfo = (TERMINFO *)lParam ;

      dwThread = GetWindowThreadProcessId(hwnd, &dwID) ;

      if(dwID == termInfo->dwID && termInfo->dwThread == dwThread )
      {
         PostMessage(hwnd, WM_CLOSE, 0, 0) ;
      }

      return TRUE ;
   }
				

Proprietā

Identificativo articolo: 178893 - Ultima modifica: martedė 13 luglio 2004 - Revisione: 2.4
Le informazioni in questo articolo si applicano a:
  • Microsoft Win32 Application Programming Interface alle seguenti piattaforme
    • Microsoft Windows 95
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
Chiavi: 
kbmt kbhowto kbkernbase kbthread KB178893 KbMtit
Traduzione automatica articoli
Il presente articolo č stato tradotto tramite il software di traduzione automatica di Microsoft e non da una persona. Microsoft offre sia articoli tradotti da persone fisiche sia articoli tradotti automaticamente da un software, in modo da rendere disponibili tutti gli articoli presenti nella nostra Knowledge Base nella lingua madre dell?utente. Tuttavia, un articolo tradotto in modo automatico non č sempre perfetto. Potrebbe contenere errori di sintassi, di grammatica o di utilizzo dei vocaboli, pių o meno allo stesso modo di come una persona straniera potrebbe commettere degli errori parlando una lingua che non č la sua. Microsoft non č responsabile di alcuna imprecisione, errore o danno cagionato da qualsiasi traduzione non corretta dei contenuti o dell?utilizzo degli stessi fatto dai propri clienti. Microsoft, inoltre, aggiorna frequentemente il software di traduzione automatica.
Clicca qui per visualizzare la versione originale in inglese dell?articolo: 178893
LE INFORMAZIONI CONTENUTE NELLA MICROSOFT KNOWLEDGE BASE SONO FORNITE SENZA GARANZIA DI ALCUN TIPO, IMPLICITA OD ESPLICITA, COMPRESA QUELLA RIGUARDO ALLA COMMERCIALIZZAZIONE E/O COMPATIBILITA' IN IMPIEGHI PARTICOLARI. L'UTENTE SI ASSUME L'INTERA RESPONSABILITA' PER L'UTILIZZO DI QUESTE INFORMAZIONI. IN NESSUN CASO MICROSOFT CORPORATION E I SUOI FORNITORI SI RENDONO RESPONSABILI PER DANNI DIRETTI, INDIRETTI O ACCIDENTALI CHE POSSANO PROVOCARE PERDITA DI DENARO O DI DATI, ANCHE SE MICROSOFT O I SUOI FORNITORI FOSSERO STATI AVVISATI. IL DOCUMENTO PUO' ESSERE COPIATO E DISTRIBUITO ALLE SEGUENTI CONDIZIONI: 1) IL TESTO DEVE ESSERE COPIATO INTEGRALMENTE E TUTTE LE PAGINE DEVONO ESSERE INCLUSE. 2) I PROGRAMMI SE PRESENTI, DEVONO ESSERE COPIATI SENZA MODIFICHE, 3) IL DOCUMENTO DEVE ESSERE DISTRIBUITO INTERAMENTE IN OGNI SUA PARTE. 4) IL DOCUMENTO NON PUO' ESSERE DISTRIBUITO A SCOPO DI LUCRO.

Invia suggerimenti

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com