Win32의 완전히"응용 프로그램 종료 방법

기술 자료 번역 기술 자료 번역
기술 자료: 178893 - 이 문서가 적용되는 제품 보기.
모두 확대 | 모두 축소

이 페이지에서

요약

완벽한 세계에서 프로세스에 다른 프로세스를 종료하도록 프로세스간 통신 일부 폼을 통해 요청할 수 있습니다. 하지만 원하는 종료 응용 프로그램의 소스 수준의 컨트롤이 있는 경우 다음 사용자가 이 옵션이 없을 수 있습니다. Win32에서 응용 프로그램을 종료할 보장된 "클린" 방법이 있지만 응용 프로그램에서 리소스를 정리하는 가장 좋은 방법은 사용하는 보장하기 위해 취할 수 있는 방법이 있습니다.

추가 정보

32 비트 프로세스 및 Windows 95에서 16비트 프로세스

Win32에서 운영 체제를 종료할 때 프로세스가 소유한 리소스를 정리하는 데 약속합니다. 그러나 이 프로세스 자체를 원격 연결을 통해 최종 통신 디스크로 정보의 모든 최종 플러시 작업을 수행할 수 있는 기회를 가진 않으며 해당 프로세스의 의미합니까 의미하지는지 않습니다, DLL의 PROCESS_DETACH 코드를 실행할 수 있는 기회를 갖게 됩니다. Windows 95 및 Windows NT에서 응용 프로그램을 종료하는 방지하기 위해 사용하는 것이 일반적으로 좋습니다 이유입니다.

반드시 프로세스를 종료해야 합니다 경우 다음과 같이 하십시오.
  1. 원하는 종료 프로세스가 소유하는 모든 최상위 창에 대한 WM_CLOSE를 게시하십시오. 많은 Windows 응용 프로그램을 종료하는 의해 이 메시지에 응답합니다.

    참고: WM_CLOSE 수 있는 콘솔 응용 프로그램의 응답 제어 처리기가 설치되어 있는 여부에 따라 달라집니다.

    EnumWindows()를 대상 창 핸들을 찾을 수 있습니다. 콜백 함수를 확인하고 해당 창을 프로세스 ID 종료 프로세스를 찾습니다. 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 또는 사용자 개입) 종료 부여합니다.

Windows NT의 16비트 문제

그러나 작업 Windows 95에서 16 비트 응용 프로그램에 대해 앞의 단계를, Windows NT 16 비트 응용 프로그램을 매우 다르게 작동합니다.

Windows NT에서 모든 16 비트 응용 프로그램은 가상 DOS 시스템 (VDM) 에서 실행됩니다. Windows NT의 Win32 프로세스 (NTVDM)이 이 VDM이 실행됩니다. NTVDM 프로세스의 프로세스 ID가 있습니다. 다른 Win32 프로세스 경우처럼 OpenProcess() 통해 프로세스 핸들을 얻을 수 있습니다. 그럼에도 불구하고 VDM에서 실행 중인 16비트 응용 프로그램을 프로세스 ID를 가진 및 따라서 사용하면 프로세스 핸들 OpenProcess()에서 가져올 수 없습니다. 각 16비트 응용 프로그램에서 VDM에 16비트 작업 처리 및 32 비트 스레드 실행이 있습니다. 핸들 및 스레드 ID VDMEnumTaskWOWEx() 함수 호출을 통해 찾을 수 있습니다. 자세한 내용은 Microsoft 기술 자료의 다음 문서를 참조하십시오.
175030Win32 응용 프로그램의 열거 방법
Windows NT의 16비트 응용 프로그램을 종료하는 경우 사용자의 첫 번째, 및 가장 간단한 옵션은 전체 NTVDM 프로세스를 종료할 수 있습니다. 위에서 설명한 단계를 수행하여 이 작업을 수행할 수 있습니다. NTVDM 프로세스의 프로세스 ID를 알아야 할 위에서 언급한 있는 NTVDM 프로세스를 ID를 찾을 수 있는 KB 문서 175030 참조하십시오. 이 방법의 단점은 해당 VDM 실행 중인 모든 16 비트 응용 프로그램을 닫는 것입니다. 그런 다음 이러한 목표를 아니면 다른 접근 합니다.

단일 16 비트 응용 프로그램 내에서 NTVDM 프로세스 종료할 수 원할 경우 다음을 수행해야 할 단계는 다음과 같습니다.
  1. 모든 최상위 창에 프로세스에 의해 소유하고 종료 16 비트 작업 동일한 소유 스레드 ID를 갖고 있는 WM_CLOSE를 게시하십시오. 이렇게 하는 가장 효과적인 방법은 EnumWindows() 사용하는 것입니다. 콜백 함수에 창의 프로세스 ID와 스레드 ID를 종료 16 비트 작업을 일치하는지 확인하십시오. 16비트 응용 프로그램이 실행되는 NTVDM 프로세스의 프로세스 ID를 수 있도록 프로세스 ID를 이동하는 기억해야 합니다.
  2. 스레드 ID를 있지만 16비트 프로세스 종료를 기다리는 방법이 없습니다. 결과적으로, 임의의 길이를 시간 (클린 종료 허용)을 위한 기다렸다가 그래도 응용 프로그램을 종료하는 데 시도하십시오 합니다. 응용 프로그램이 이미 종료되었는지 다음 이 아무 작업도 수행합니다. 종료되지 않은 응용 프로그램을 종료합니다.
  3. 찾을 수 있는 Vdmdbg.dll VDMTerminateTaskWOW() 라는 함수를 사용하여 응용 프로그램을 종료하십시오. 프로세스 ID를 사용하여 VDM 및 16 비트 작업의 작업 번호를 사용합니다.
이 방법을 사용하면 Windows NT의 VDM 내에서 단일 16 비트 응용 프로그램을 종료할 수 있습니다. 그러나 16비트 Windows 매우 좋은 종료된 작업의 리소스를 정리하는 시 아니고 둘 다 있는 VDM 실행하는 WOWExec. Windows NT의 16비트 응용 프로그램을 종료하는 데 cleanest 가능한 방법을 찾는 경우 전체 VDM 프로세스를 종료하면 고려해야 합니다. 참고: 나중에 종료할 수 있는 16 비트 응용 프로그램을 시작하는 경우, 다음, CREATE_SEPARATE_WOW_VDM을 CreateProcess() 함께 사용하십시오.

예제 코드

샘플 코드는 다음 두 함수를 사용하는 16비트 및 32비트 응용 프로그램은 위에서 설명한 기술을 구현하는: TerminateApp() 및 Terminate16App(). TerminateApp() (밀리초는 에서) 32비트 프로세스 ID 및 시간 제한을 사용합니다. Terminate16App()입니다. 두 함수 모두 이러한 이진 호환 Windows NT 및 Windows 95 걸쳐 수 있도록 DLL 함수에 명시적 링크를 사용합니다.
   //******************
   //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 - 마지막 검토: 2004년 7월 13일 화요일 - 수정: 2.4
본 문서의 정보는 다음의 제품에 적용됩니다.
  • Microsoft Win32 Application Programming Interface?을(를) 다음과 함께 사용했을 때
    • Microsoft Windows 95
    • Microsoft Windows NT 4.0
    • the operating system: Microsoft Windows 2000
    • the operating system: Microsoft Windows XP
키워드:?
kbmt kbhowto kbkernbase kbthread KB178893 KbMtko
기계 번역된 문서
중요: 본 문서는 전문 번역가가 번역한 것이 아니라 Microsoft 기계 번역 소프트웨어로 번역한 것입니다. Microsoft는 번역가가 번역한 문서 및 기계 번역된 문서를 모두 제공하므로 Microsoft 기술 자료에 있는 모든 문서를 한글로 접할 수 있습니다. 그러나 기계 번역 문서가 항상 완벽한 것은 아닙니다. 따라서 기계 번역 문서에는 마치 외국인이 한국어로 말할 때 실수를 하는 것처럼 어휘, 구문 또는 문법에 오류가 있을 수 있습니다. Microsoft는 내용상의 오역 또는 Microsoft 고객이 이러한 오역을 사용함으로써 발생하는 부 정확성, 오류 또는 손해에 대해 책임을 지지 않습니다. Microsoft는 이러한 문제를 해결하기 위해 기계 번역 소프트웨어를 자주 업데이트하고 있습니다.

피드백 보내기

 

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