Cómo terminar una aplicación "Limpia" en Win32

Seleccione idioma Seleccione idioma
Id. de artículo: 178893 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Resumen

En un mundo perfecto, el proceso podría pedir otro proceso a través de alguna forma de comunicación entre procesos, para apagar. Sin embargo, si no tiene control de nivel de origen de la aplicación que desea apagar, a continuación, puede que no tiene esta opción. Aunque no hay ninguna garantizada forma "limpia" para cerrar una aplicación en Win32, están pasos que puede realizar para asegurarse de que la aplicación utiliza el mejor método para limpiar los recursos.

Más información

Procesos de 32 bits (y procesos de 16 bits en Windows 95)

En Win32, el sistema operativo promete limpiar los recursos propiedad de un proceso cuando se apaga. No, sin embargo, significa que el proceso ha tenido la oportunidad para realizar los vaciados finales de información de disco, cualquier comunicación final a través de una conexión remota, ni significa que el proceso DLL tendrá la oportunidad para ejecutar su código PROCESS_DETACH. Este es el motivo es normalmente preferible evitar la terminación de una aplicación en Windows 95 y Windows NT.

Si es absolutamente debe cerrar un proceso, siga estos pasos:
  1. Contabilizar todas ventanas de nivel superior correspondientes por el proceso que desea apagar una se ha WM_CLOSE. Muchas aplicaciones de Windows se responda a este mensaje cerrando.

    Nota : respuesta de una aplicación consola a se ha WM_CLOSE depende de si o no ha instalado un controlador de control.

    Utilice EnumWindows() para buscar los controladores para las ventanas de destino. En la función de devolución de llamada, comprobar si las ventanas ID. de proceso coincide con el proceso que desea cerrar. Puede hacerlo llamando a GetWindowThreadProcessId(). Una vez establecida a una coincidencia, utilice PostMessage() o SendMessageTimeout() para registrar el mensaje se ha WM_CLOSE a la ventana.
  2. Utilice WaitForSingleObject() espera para el identificador del proceso. Asegúrese de que espera con un valor de tiempo de espera porque existen muchas situaciones en que la se ha WM_CLOSE no cerrará la aplicación. Recuerde que el tiempo de espera lo suficientemente largo (ya sea con WaitForSingleObject(), o con SendMessageTimeout()) forma que un usuario pueda responder a cualquier cuadro de diálogo cuadros que se crearon en respuesta al mensaje se ha WM_CLOSE.
  3. Si el valor devuelto es WAIT_OBJECT_0, a continuación, cierra la aplicación propia limpiamente. Si el valor devuelto es WAIT_TIMEOUT, deberá utilizar TerminateProcess() para cerrar la aplicación.

    Nota : si están getting3 valor de una devolución de WaitForSingleObject() otros, a continuación, WAIT_OBJECT_0 o WAIT_TIMEOUT, utilice GetLastError() para determinar la causa.
Dé siguiendo estos pasos, a la aplicación la mejor oportunidad posible cerrar limpiamente (aparte de IPC o intervención del usuario).

El problema de 16 bits (en Windows NT)

Anterior los pasos de trabajo para aplicaciones de 16 bits en Windows 95, sin embargo, las aplicaciones de Windows de 16 bits funcionan muy distinta.

En Windows NT, todas las aplicaciones de 16 bits se ejecutan en una máquina DOS virtual (VDM). Este VDM se ejecuta como un proceso de Win32 (NTVDM) en Windows NT. El proceso NTVDM tiene un identificador del proceso. Puede obtener un identificador del proceso a través de OpenProcess(), igual que con cualquier otro proceso de Win32. No obstante, ninguna de las aplicaciones de 16 bits que se ejecutan en el VDM tiene un identificador de proceso y, por lo tanto, no se obtendrá un identificador de proceso de OpenProcess(). Cada aplicación de 16 bits en una VDM tiene un identificador de tarea de 16 bits y un subproceso de 32 bits de ejecución. Puede encontrar el identificador de identificador y el subproceso mediante una llamada a la función VDMEnumTaskWOWEx(). Para obtener información adicional, consulte en contacto con el siguiente artículo en Microsoft Knowledge Base:
175030Cómo enumerar las aplicaciones de Win32
La opción primera y más sencilla, al apagar una aplicación de 16 bits en Windows NT es cerrar todo el proceso NTVDM. Puede hacerlo siguiendo los pasos descritos anteriormente. Sólo necesita conocer el identificador del proceso del proceso NTVDM (consulte la KB artículo 175030 citados anteriormente para buscar el identificador de proceso de NTVDM). La desventaja de este enfoque es que cierra todas las aplicaciones de 16 bits que se ejecutan en ese VDM. Si no es su objetivo, deberá adoptar otro enfoque.

Si desea cerrar una aplicación de 16 bits única dentro de un proceso NTVDM son: los pasos que necesarios para tomar
  1. Contabilizar todas ventanas de nivel superior que posea el proceso y que tengan el mismo ID de subproceso propietario que la tarea de 16 bits que desea apagar una se ha WM_CLOSE. La forma más eficaz de hacerlo es utilizar EnumWindows(). En la función de devolución de llamada, compruebe si la ventana ID. de proceso y subproceso ID coincide con la tarea de 16 bits que desea cerrar. Recuerde que el identificador de proceso se va a ser el identificador de proceso del proceso NTVDM en la que se ejecuta la aplicación de 16 bits.
  2. Aunque tienen un identificador de subproceso, no dispone de ninguna manera para esperar en la terminación del proceso 16 bits. Como resultado, debe esperar un intervalo arbitrario de tiempo (para permitir que un limpio apaga) y, a continuación, intente apagar la aplicación de todos modos. Si ya ha cerrado la aplicación, a continuación, esto no hará nada. Si no cierra, finalizará la aplicación.
  3. Terminar la aplicación utilizando una función denominada VDMTerminateTaskWOW(), que puede encontrarse en el Vdmdbg.dll. Toma el identificador de proceso de la VDM y el número de tarea de la tarea de 16 bits.
Este enfoque permite cerrar una aplicación única de 16 bits dentro de una VDM en Windows NT. Sin embargo, Windows de 16 bits no es muy bueno en Limpiar los recursos de una tarea terminada y ninguno es el WOWExec ejecutando en el VDM. Si está buscando el enfoque posible cleanest para terminar una aplicación de 16 bits en Windows NT, debe considerar la terminación del proceso VDM todo. Nota: Si está iniciando una aplicación de 16 bits que puede finalizar más tarde, a continuación, utilice el CREATE_SEPARATE_WOW_VDM con CreateProcess().

Código de ejemplo

El código de ejemplo implementa las técnicas descritas anteriormente para aplicaciones de 16 bits y 32 bits que se utilizan las dos funciones siguientes: TerminateApp() y Terminate16App(). TerminateApp() toma un identificador de proceso de 32 bits y un tiempo de espera (en milisegundos realizar operaciones). Terminate16App(). Ambas funciones utilizan la vinculación explícita a funciones DLL para que sea compatible con binarios a través de Windows NT y 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 ;
   }
				

Propiedades

Id. de artículo: 178893 - Última revisión: martes, 13 de julio de 2004 - Versión: 2.4
La información de este artículo se refiere a:
  • Microsoft Win32 Application Programming Interface sobre las siguientes plataformas
    • Microsoft Windows 95
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
Palabras clave: 
kbmt kbhowto kbkernbase kbthread KB178893 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 178893

Enviar comentarios

 

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