Как остановить приложение «Чисто» в Win32

Переводы статьи Переводы статьи
Код статьи: 178893 - Vizualiza?i produsele pentru care se aplic? acest articol.
Развернуть все | Свернуть все

В этой статье

Аннотация

В идеальном мире процесс попросить другого процесса, через некоторые форма межпроцессного взаимодействия, чтобы завершить работу. Тем не менее если не задан Контроль исходного уровня приложения, которое вы хотите завершить работу, Затем у этого параметра. Несмотря на то, что существует не гарантируется, что «чистое» до завершения работы приложения Win32, существуют действия, которые можно предпринять Чтобы убедиться, что приложение использует наилучший метод очистки ресурсы.

Дополнительная информация

32-Разрядные процессы (и 16-разрядных процессов в среде Windows 95)

Под Win32, обещает освободить ресурсы, принадлежащие операционной системы процесс при завершении работы. Это, однако, означает, что процесс сам имел возможность сделать любой окончательной очистки сведения для диск любого окончательного связи через удаленное соединение и не означает Этот процесс DLL будет иметь возможность выполнения своих Код PROCESS_DETACH. Поэтому обычно предпочтительнее избежать Завершение работы приложения в Windows 95 и Windows NT.

Если совершенно необходимо завершить работу процесса, выполните следующие действия.
  1. Учет WM_CLOSE всем окнам верхнего уровня, владельцем процесса, который необходимо завершить работу. Многие приложения Windows ответить на это сообщение по завершении работы.

    ПРИМЕЧАНИЕ: Ответ консольное приложение WM_CLOSE зависит ли она установлена обработчик управления.

    Используйте EnumWindows() для поиска маркеры для целевого окна. В функции обратного вызова посмотрите, если идентификатор процесса windows соответствующий процесс, чтобы завершить работу. Это можно сделать путем вызова GetWindowThreadProcessId(). После установления соответствия с помощью PostMessage() или SendMessageTimeout() Чтобы разместить сообщение WM_CLOSE в окно.
  2. Используйте WaitForSingleObject() для ожидания дескриптора процесса. Убедитесь, что ожидания со значением времени ожидания, так как существует множество ситуаций, в которых WM_CLOSE не завершит работу приложения. Помните, что время ожидания, достаточно долго (или с WaitForSingleObject(), с помощью SendMessageTimeout()) таким образом, пользователь может отвечать на любом диалоговом окне полей, созданных в ответ на сообщение WM_CLOSE.
  3. Если возвращаемым значением является WAIT_OBJECT_0, затем приложение закрывается сам аккуратно. Если возвращаемое значение WAIT_TIMEOUT, необходимо использовать TerminateProcess() для завершения работы приложения.

    ПРИМЕЧАНИЕ: Getting3, возврат значения из других WaitForSingleObject(), а затем WAIT_OBJECT_0 или WAIT_TIMEOUT, используйте GetLastError() для определения причины.
Выполнив эти действия, дать приложению максимально для завершения работы штатному (не считая IPC или вмешательства пользователя).

Проблема 16-разрядные (под Windows NT)

Указанные выше действия работы 16-разрядных приложений в среде Windows 95, тем не менее, Windows NT 16-разрядным приложениям работать очень по-разному.

В системе Windows NT все 16-разрядные приложения выполняются в виртуальной машины DOS (VDM). это VDM запускается как процесс Win32 (NTVDM) в системе Windows NT. NTVDM процесс имеет идентификатор процесса. Получение дескриптора процесса через OpenProcess(), так же, как можно в любом другом процессе Win32. Тем не менее, ни для одного из 16-разрядных приложений, работающих в VDM не Идентификатор процесса, и поэтому не удается получить дескриптор процесса из OpenProcess(). Каждый 16-разрядного приложения в VDM содержит 16-разрядные задачи, обработки и 32-разрядных поток исполнения. Можно найти идентификатор дескриптора и потока путем вызова функции VDMEnumTaskWOWEx(). Для дополнительной сведения, обратитесь к следующей статье базы знаний Майкрософт Основание:
175030Как выполнить перечисление приложений в Win32
Первый и самый простой команды завершения работы 16-разрядных приложения в системе Windows NT является завершение весь процесс NTVDM. Вы Это можно сделать, выполнив шаги, описанные выше. Необходимо знать Идентификатор процесса NTVDM (см. статью КБ 175030 обозначенной выше Чтобы найти идентификатор процесса NTVDM.) Недостатком этого подхода является то, что Закрывает все 16-разрядные приложения, запущенные в этом VDM. Если это не Ваша цель, то вы должны принять другой подход.

Если вы хотите завершить работу одного 16-разрядного приложения в рамках NTVDM процесс, ниже приведены шаги, которые необходимо выполнить.
  1. Учет windows, принадлежащие процессу, WM_CLOSE для всех верхнего уровня и, имеют тот же код потока-владельца, как 16-разрядные задачи, необходимо Завершение работы. — Это наиболее эффективный способ сделать это с помощью EnumWindows(). В функции обратного вызова, проверьте Если окно идентификатор процесса, и Идентификатор потока обозначает 16-разрядные задачи, необходимо завершить работу. Помните, что Идентификатор процесса, который должен стать идентификатор процесса NTVDM в который работает 16-разрядного приложения.
  2. Несмотря на то, что у вас есть идентификатор потока, у вас нет возможности ожидать Завершение 16-разрядный процесс. Таким образом, необходимо дождаться произвольный промежуток времени (позволяющие завершения работы) и повторите попытку Несмотря на это завершение работы приложения. Если приложение уже завершил вниз затем это не делает ничего. Если он еще не завершит работу, затем он будет завершить работу приложения.
  3. Завершить работу приложения, используя функцию с именем VDMTerminateTaskWOW(), что можно найти в Vdmdbg.dll. Получает идентификатор процесса VDM и номер задачи в 16-разрядные задачи.
Такой подход позволяет завершить работу одного 16-разрядного приложения в VDM в системе Windows NT. Однако 16-разрядной версии Windows не очень удобен для очистки ресурсы прерванные задачи, и ни один из них является WOWExec, в VDM. Если вы ищете cleanest возможных подходов к Завершение 16-разрядных приложений под Windows NT, следует рассмотреть возможность Завершение всего процесса VDM. Примечание: При запуске 16-разрядных приложение, которое может прекратить действие позже, то используйте CREATE_SEPARATE_WOW_VDM с CreateProcess().

Пример кода

Образец кода реализует методы, описанные выше, для 16-разрядных и 32- бит приложения, используя следующие две функции: TerminateApp() и Terminate16App(). TerminateApp() принимает код 32-разрядного процесса и тайм-аут (в миллисекундах). Terminate16App(). Обе функции используйте явное связывание Функции библиотеки DLL, так, чтобы они двоичной совместимостью между Windows NT и 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 ;
   }
				

Свойства

Код статьи: 178893 - Последний отзыв: 23 сентября 2011 г. - Revision: 5.0
Информация в данной статье относится к следующим продуктам.
  • Microsoft Win32 Application Programming Interface
Ключевые слова: 
kbhowto kbkernbase kbthread kbmt KB178893 KbMtru
Переведено с помощью машинного перевода
ВНИМАНИЕ! Перевод данной статьи был выполнен не человеком, а с помощью программы машинного перевода, разработанной корпорацией Майкрософт. Корпорация Майкрософт предлагает вам статьи, переведенные как людьми, так и средствами машинного перевода, чтобы у вас была возможность ознакомиться со статьями базы знаний KB на родном языке. Однако машинный перевод не всегда идеален. Он может содержать смысловые, синтаксические и грамматические ошибки, подобно тому как иностранец делает ошибки, пытаясь говорить на вашем языке. Корпорация Майкрософт не несет ответственности за неточности, ошибки и возможный ущерб, причиненный в результате неправильного перевода или его использования. Корпорация Майкрософт также часто обновляет средства машинного перевода.
Эта статья на английском языке:178893

Отправить отзыв

 

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