DetailPage-MSS-KB

Base de Dados de Conhecimento

Artigo: 178893 - Última revisão: terça-feira, 13 de Julho de 2004 - Revisão: 2.4

 

Nesta página

Sumário

Num mundo ideal, o processo foi peça ao outro processo, através de alguma forma de comunicação entre processos, a encerrar. No entanto, se não tiver o controlo de origem nível da aplicação que pretende encerrar, em seguida, poderá não ter esta opção. Embora não exista nenhuma forma de "limpa" garantida para encerrar uma aplicação no Win32, existem passos que pode tomar para garantir que a aplicação utiliza o melhor método para limpar recursos.

Mais Informação

Processos de 32 bits (e processos de 16 bits no Windows 95)

No Win32, o sistema operativo promete limpar recursos pertencentes a um processo quando é encerrado. Isto não, no entanto, significa que o processo próprio teve a oportunidade de efectuar qualquer alinhamentos finais das informações aos discos, qualquer comunicação final através de uma ligação remota, nem significa que o processo DLL terá a oportunidade de executar o respectivo código PROCESS_DETACH. É por isso é geralmente preferível evitar terminar uma aplicação em Windows 95 e Windows NT.

Se for absolutamente tem de encerrar um processo, siga estes passos:
  1. Colocar um WM_CLOSE todas as janelas de nível superiores pertencentes o processo que pretende encerrar. Muitas aplicações do Windows responder a esta mensagem ao encerrar.

    Nota : resposta de uma aplicação de consola a WM_CLOSE depende se instalou um processador de controlo.

    Utilize EnumWindows() para localizar as alças para as janelas de destino. A função de chamada de retorno, verifique se as janelas processam ID corresponde a processo que pretende encerrar. Pode fazê-lo chamando GetWindowThreadProcessId(). Depois de ter estabelecido uma correspondência, utilize PostMessage() ou SendMessageTimeout() para colocar a mensagem WM_CLOSE para a janela.
  2. Utilize WaitForSingleObject() para aguardar a alça do processo. Certifique-se que esperar com um valor de tempo de espera, uma vez que existem muitas situações em que o WM_CLOSE não encerrará a aplicação. Lembre-se efectuar o tempo limite tempo suficiente (com WaitForSingleObject() ou com SendMessageTimeout()) forma a que um utilizador possa responder a qualquer caixa de diálogo caixas que foram criados em resposta à mensagem WM_CLOSE.
  3. Se o valor de retorno WAIT_OBJECT_0, em seguida, a aplicação fechado próprio correctamente. Se o valor devolvido é WAIT_TIMEOUT, tem de utilizar TerminateProcess() para encerrar a aplicação.

    Nota : Se forem getting3 valor um retorno de WaitForSingleObject() outros, em seguida, WAIT_OBJECT_0 ou WAIT_TIMEOUT, utilize GetLastError() para determinar a causa.
Seguindo estes passos, é atribuir a aplicação a melhor hipótese possível encerrar correctamente (para além da IPC ou intervenção do utilizador).

O problema de 16 bits (no Windows NT)

O anterior passos trabalho para aplicações de 16 bits no Windows 95, no entanto, as aplicações do Windows NT 16-bit funcionar muito diferente.

No Windows NT, todas as aplicações de 16 bits executadas no virtual DOS machine (VDM). Este VDM é executado como um processo do Win32 (NTVDM) no Windows NT. O processo NTVDM tem um ID de processo. Pode obter um identificador para o processo através do OpenProcess(), tal como acontece com qualquer outro processo do Win32. No entanto, nenhuma das aplicações de 16 bits em execução no VDM têm um ID de processo e, por isso, não é possível receber um identificador de processo de OpenProcess(). Cada aplicação de 16 bits numa VDM tem um identificador de tarefas de 16 bits e um thread de 32 bits de execução. É possível encontrar o ID de identificador e o thread através de uma chamada para a função VDMEnumTaskWOWEx(). Para obter informações adicionais, consulte o seguinte artigo na base de dados de conhecimento da Microsoft:
175030  (http://support.microsoft.com/kb/175030/EN-US/ ) Como enumerar aplicações no Win32
A opção primeira e mais simples, quando uma aplicação de 16 bits no Windows NT a ser encerrado é encerrado todo o processo NTVDM. Pode fazê-lo seguindo os passos descritos acima. Só precisa de saber o ID do processo NTVDM (consulte o KB artigo 175030  (http://support.microsoft.com/kb/175030/EN-US/ ) citados acima para localizar o ID de processo de um NTVDM). A desvantagem desta abordagem é que fecha todos os 16 bits aplicações em execução em que VDM. Se não for este o objectivo, terá de efectuar outra abordagem.

Se pretender encerrar uma única aplicação 16 bits num processo NTVDM, seguem-se os passos que necessários para tirar:
  1. Colocar um WM_CLOSE todas as janelas de nível superiores que são propriedade pelo processo e que têm o mesmo ID de thread proprietário como a tarefa de 16 bits que pretende encerrar. A forma mais eficaz para o fazer é utilizando EnumWindows(). Na função de chamada de retorno, verifique se a janela ID de processo e ID do thread corresponde a tarefa de 16 bits que pretende encerrar. Lembre-se que o ID do processo vai ser o ID do processo NTVDM no qual a aplicação de 16 bits esteja em execução.
  2. Apesar de ter um ID de thread, não tem maneira de esperar no fim do processo de 16 bits. Como consequência, tem de aguardar por um período de tempo (para permitir que encerra uma raiz) arbitrário e tente encerrar a aplicação na mesma. Se a aplicação já foi encerrado, este irá faça nada. Se este ainda não encerrado, em seguida, irá terminar a aplicação.
  3. Termine a aplicação utilizando uma função chamada VDMTerminateTaskWOW(), poderá encontrar o Vdmdbg.dll. Demora o ID de processo do VDM e o número tarefa da tarefa de 16 bits.
Esta abordagem permite-lhe encerrar uma única aplicação 16-bit dentro de uma VDM no Windows NT. No entanto, de 16 bits do Windows não não muito boa ao limpar recursos de uma tarefa terminada e nenhum estiver WOWExec com o VDM. Se estiver a procurar a abordagem possível cleanest para terminar uma aplicação de 16 bits no Windows NT, deve considerar terminar todo o processo VDM. NOTA: Se estiver a iniciar uma aplicação de 16 bits que pode concluir mais tarde, em seguida, utilize o CREATE_SEPARATE_WOW_VDM com CreateProcess().

Código de exemplo

O código de exemplo implementa as técnicas descritas acima para aplicações de 16 bits e 32 bits utilizando as seguintes duas funções: TerminateApp() e Terminate16App(). TerminateApp() tem um ID de processo de 32 bits e um limite de tempo (em miliseconds). Terminate16App(). Ambas funções de utilizam explícita ligar DLL funções para que estes binários compatíveis através de 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 ;
   }
				

A informação contida neste artigo aplica-se a:
  • Microsoft Win32 Application Programming Interface nas seguintes plataformas
    • Microsoft Windows 95
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
Palavras-chave: 
kbmt kbhowto kbkernbase kbthread KB178893 KbMtpt
Tradução automáticaTradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine translation ou MT), não tendo sido portanto revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática… erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 178893  (http://support.microsoft.com/kb/178893/en-us/ )
Partilhar
Opções de suporte adicionais
Fóruns de Suporte da Comunidade Microsoft
Contacte-nos directamente
Encontre um parceiro certificado Microsoft
Loja Microsoft