分类: C/C++
2008-08-01 17:08:34
此方法允许你关闭 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下载本文示例代码#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 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 ; }