WEB开发网
开发学院软件开发VC 如何“干净地”终止 Win32 中的应用程序 阅读

如何“干净地”终止 Win32 中的应用程序

 2008-09-19 19:27:25 来源:WEB开发网   
核心提示: 尽管你有线程 ID,但无法等待 16 位进程的终止,如何“干净地”终止 Win32 中的应用程序(3),因此,你必须等待任意时间长度(以允许干净关闭),如果超时,则干掉它.if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0) dw

尽管你有线程 ID,但无法等待 16 位进程的终止。因此,你必须等待任意时间长度(以允许干净关闭),然后尝试关闭应用程序。如果应用程序已关闭,则此操作无效。如果应用程序尚未关闭,则它将终止应用程序。

使用称为 VDMTerminateTaskWOW() 的函数终止应用程序,该函数可在 Vdmdbg.dll 中找到。它采用 VDM 的进程 ID 和 16 位任务的任务编号。

此方法允许你关闭 Windows NT 下 VDM 中的单个 16 位应用程序。不过,16 位 Windows 以及 VDM 中运行的 WOWExec 都不能有效地清除已终止任务的资源。如果你要寻找最有可能干净地终止 Windows NT 下的 16 位应用程序的方法,应考虑终止整个 VDM 进程。注意:如果你要启动以后可能会终止的 16 位应用程序,请将 CREATE_SEPARATE_WOW_VDM 与 CreateProcess() 结合使用。

示例代码

下面的示例代码使用以下两个函数实现上述用于 16 位和 32 位应用程序的方法:TerminateApp() 和 Terminate16App()。TerminateApp() 采用一个 32 位进程 ID 和一个超时值(以毫秒为单位)。Terminate16App()。这两个函数都使用 DLL 函数的显式链接,以便它们的二进制文件与 Windows NT 和 Windows 95 都兼容。

  //******************
  // 头文件 TermApp.h
  //******************
  #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 );
  //*********************
  // 实现代码 TermApp.cpp
  //*********************
  #include "TermApp.h"
  #include <vdmdbg.h>
  typedef struct
  {
   DWORD  dwID ;
   DWORD  dwThread ;
  } TERMINFO ;
  // 声明回调枚举函数.
  BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;
  BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam ) ;
  /*----------------------------------------------------------------
  DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )
  功能:
   关闭 32-位进程(或 Windows 95 下的 16-位进程)
  参数:
   dwPID
     要关闭之进程的进程 ID.
   dwTimeout
     进程关闭前等待的毫秒时间.
  返回值:
   TA_FAILED —— 如果关闭失败.
   TA_SUCCESS_CLEAN —— 如果使用 WM_CLOSE 关闭了进程.
   TA_SUCCESS_KILL —— 如果使用 TerminateProcess() 关闭了进程.
   返回值的定义参见头文件.
  ----------------------------------------------------------------*/
  DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )
  {
   HANDLE  hProc ;
   DWORD  dwRet ;
   // 如果无法用 PROCESS_TERMINATE 权限打开进程,那么立即放弃。
   hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,dwPID);
   if(hProc == NULL)
   {
     return TA_FAILED ;
   }
   // TerminateAppEnum() 将 WM_CLOSE 消息发到所有其进程ID 与你所提供的进程ID 匹配的窗口.
   EnumWindows((WNDENUMPROC)TerminateAppEnum, (LPARAM) dwPID) ;
   // 等待处理,如果成功,OK。如果超时,则干掉它.
   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 )
  功能:
   关闭 Win16 应用程序.
  参数:
   dwPID
     16-位程序运行其中的 NTVDM 进程 ID.
   dwThread
     16-位程序中执行线程的线程 ID.
   w16Task
     应用程序的 16-位任务句柄.
   dwTimeout
     任务关闭前等待的毫秒时间.
  返回值:
   如果成功, 返回 TA_SUCCESS_16
   如果不成功, 返回 TA_FAILED.   
    返回值的定义参见该函数的头文件.
  注意:
   你可以通过 VDMEnumTaskWOW() 或 VDMEnumTaskWOWEx() 函数获得 Win16 和线程 ID.
  ----------------------------------------------------------------*/
  DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,
            WORD w16Task, DWORD dwTimeout )
  {
   HINSTANCE   hInstLib ;
   TERMINFO   info ;
   // 你必须通过外部链接调用函数,以便代码在所有 Win32 平台上都兼容。
   BOOL (WINAPI *lpfVDMTerminateTaskWOW)(DWORD dwProcessId,WORD htask) ;
   hInstLib = LoadLibraryA( "VDMDBG.DLL" ) ;
   if( hInstLib == NULL )
     return TA_FAILED ;
   // 获得函数过程地址.
   lpfVDMTerminateTaskWOW = (BOOL (WINAPI *)(DWORD, WORD ))
     GetProcAddress( hInstLib, "VDMTerminateTaskWOW" ) ;
   if( lpfVDMTerminateTaskWOW == NULL )
   {
     FreeLibrary( hInstLib ) ;
     return TA_FAILED ;
   }
   // 向所有匹配进程 ID 和线程的窗口发送 WM_CLOSE 消息.
   info.dwID = dwPID ;
   info.dwThread = dwThread ;
   EnumWindows((WNDENUMPROC)Terminate16AppEnum, (LPARAM) &info) ;
   // 等待.
   Sleep( dwTimeout ) ;
   // 然后终止.
   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 ;
  }  

上一页  1 2 3 

Tags:如何 干净 终止

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接