如何“干净地”终止 Win32 中的应用程序
2008-09-19 19:27:25 来源:WEB开发网尽管你有线程 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 ;
}
更多精彩
赞助商链接