日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2025/3/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何“干净地”终止 Win32 中的应用程序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

如何“干凈地”終止 Win32 中的應用程序

察看這篇文章對應的產品
文章 ID:178893
最后更新日期:2004年11月25日
版本:2.2
本頁內容
概要
更多信息
?32 位進程(和 Windows 95 下的 16 位進程)
?16 位問題(在 Windows NT 下)
?示例代碼
這篇文章中的信息適用于:

概要

在理想環境中,某一進程可能會通過某種形式的進程間通信要求另一進程關閉。不過,如果您對希望其關閉的應用程序沒有源代碼級控制權,可能就無法選擇這樣做。盡管沒有哪種方法保證可以“干凈地”關閉 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() 關閉應用程序。

注意:如果您從 WaitForSingleObject() 得到的返回值不是 WAIT_OBJECT_0 或 WAIT_TIMEOUT,則應使用 GetLastError() 找出原因。
通過執行上述這些步驟,您就為應用程序提供了干凈(無需 IPC 或用戶干預)關閉的最佳機會。

16 位問題(在 Windows NT 下)

上述步驟適用于 Windows 95 下的 16 位應用程序,而 Windows NT 下的 16 位應用程序與 Windows 95 下的 16 位應用程序的工作方式差別非常大。

在 Windows NT 下,所有 16 位應用程序都在虛擬 DOS 機 (VDM) 中運行。此 VDM 是作為 Windows NT 下的一個 Win32 進程 (NTVDM) 運行的。NTVDM 進程具有進程 ID。您可以通過 OpenProcess() 獲取該進程的句柄,就像處理其他任何 Win32 進程一樣。不過,在 VDM 中運行的 16 位應用程序都沒有進程 ID,因此您無法從 OpenProcess() 獲取進程句柄。VDM 中的每個 16 位應用程序都有一個 16 位任務句柄和一個 32 位執行線程。可通過調用函數 VDMEnumTaskWOWEx() 找到該任務句柄和線程 ID。有關其他信息,請參見以下 Microsoft 知識庫文章: 175030 如何使用 Win32 API 來枚舉應用程序 關閉 Windows NT 下的 16 位應用程序的首選和最直接的方法是關閉整個 NTVDM 進程。您可以通過執行前面概述的步驟來完成此操作。您只需知道 NTVDM 的進程 ID 即可(請參見前面引用的知識庫文章175030 來查找 NTVDM 的進程 ID)。此方法的缺點是它會關閉在該 VDM 中運行的所有 16 位應用程序。如果這不是您想要的結果,則需要采取其他方法。

如果您希望關閉 NTVDM 進程中的單個 16 位應用程序,需要按照下列步驟操作:
1.向該進程所擁有的以及與您要關閉的 16 位任務具有相同線程 ID 的所有頂級窗口發送一條 WM_CLOSE 消息。執行此操作最有效的方法是使用 EnumWindows()。在回調函數中,檢查窗口的進程 ID 和線程 ID 是否與要關閉的 16 位任務相匹配。請記住,該進程 ID 將成為在其中運行 16 位應用程序的 NTVDM 的進程 ID。
2.盡管您有線程 ID,但無法等待 16 位進程的終止。因此,您必須等待任意時間長度(以允許干凈關閉),然后嘗試關閉應用程序。如果應用程序已關閉,則此操作無效。如果應用程序尚未關閉,則它將終止應用程序。
3.使用稱為 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 都兼容。 //******************//Header//******************#include <windows.h>#define TA_FAILED 0#define TA_SUCCESS_CLEAN 1#define TA_SUCCESS_KILL 2#define TA_SUCCESS_16 3DWORD 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:dwPIDProcess ID of the process to shut down.dwTimeoutWait 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 withTerminateProcess().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);elsedwRet = 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:dwPIDProcess ID of the NTVDM in which the 16-bit application isrunning.dwThreadThread ID of the thread of execution for the 16-bitapplication.w16Task16-bit task handle for the application.dwTimeoutWait time in milliseconds before shutting down the task.Return Value:If successful, returns TA_SUCCESS_16If unsuccessful, returns TA_FAILED.NOTE: These values are defined in the header for thisfunction.NOTE:You can get the Win16 task and thread ID through theVDMEnumTaskWOW() 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 ;}
返回頁首

這篇文章中的信息適用于:
?Microsoft Win32 Application Programming Interface (API)當用于
?Microsoft Windows 95 Service Pack 1
?Microsoft Windows NT 4.0 Service Pack 7
?Microsoft Windows 2000 Standard Edition
?Microsoft Windows XP Standard Edition
返回頁首
關鍵字:?
kbhowto kbkernbase kbthread KB178893
返回頁首
Microsoft和/或其各供應商對于為任何目的而在本服務器上發布的文件及有關圖形所含信息的適用性,不作任何聲明。 所有該等文件及有關圖形均"依樣"提供,而不帶任何性質的保證。Microsoft和/或其各供應商特此聲明,對所有與該等信息有關的保證和條件不負任何責任,該等保證和條件包括關于適銷性、符合特定用途、所有權和非侵權的所有默示保證和條件。在任何情況下,在由于使用或運行本服務器上的信息所引起的或與該等使用或運行有關的訴訟中,Microsoft和/或其各供應商就因喪失使用、數據或利潤所導致的任何特別的、

總結

以上是生活随笔為你收集整理的如何“干净地”终止 Win32 中的应用程序的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。