• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            road420

            導(dǎo)航

            <2006年10月>
            24252627282930
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            統(tǒng)計

            常用鏈接

            留言簿(2)

            隨筆檔案

            文章檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            如何“干凈地”終止 Win32 中的應(yīng)用程序

            如何“干凈地”終止 Win32 中的應(yīng)用程序

            編譯:Northtibet

          1. 摘要
          2. 32 位進(jìn)程(和 Windows 95 下的 16 位進(jìn)程)
          3. 16 位問題(在 Windows NT 下)
          4. 示例代碼
          5. 摘要

              在理想環(huán)境中,某一進(jìn)程可能會通過某種形式的進(jìn)程間通信要求另一進(jìn)程關(guān)閉。不過,如果你對希望其關(guān)閉的應(yīng)用程序沒有源代碼級控制權(quán),可能就沒有辦法做這樣的選擇。盡管沒有哪種方法能保證“干凈地”關(guān)閉 Win32 中的應(yīng)用程序,但你可以采取一些步驟來確保應(yīng)用程序使用最佳方法清除資源。

            32 位進(jìn)程(和 Windows 95 下的 16 位進(jìn)程)

              在 Win32 下,操作系統(tǒng)可保證在進(jìn)程關(guān)閉時清除進(jìn)程所擁有的資源。但是,這并不意味著進(jìn)程本身將有機(jī)會對磁盤執(zhí)行任何最后的信息刷新或通過遠(yuǎn)程連接執(zhí)行任何最后的通信,也不意味著進(jìn)程的 DLL 將有機(jī)會執(zhí)行其 PROCESS_DETACH 代碼。這就是通常最好避免在 Windows 95 和 Windows NT 下終止應(yīng)用程序的原因。

            如果你必須關(guān)閉進(jìn)程,請按照下列步驟操作:

            1. 向你打算關(guān)閉的進(jìn)程所擁有的所有頂級窗口發(fā)送一條 WM_CLOSE 消息。許多 Windows 應(yīng)用程序會通過關(guān)閉它自身來響應(yīng)此消息。

              注意:控制臺應(yīng)用程序?qū)?WM_CLOSE 的響應(yīng)取決于它是否安裝了控制處理程序。

              使用 EnumWindows() 找到目標(biāo)窗口的句柄。在回調(diào)函數(shù)中,檢查該窗口的進(jìn)程 ID 是否與要關(guān)閉的進(jìn)程相匹配。你可以通過調(diào)用 GetWindowThreadProcessId() 來執(zhí)行此操作。確定匹配項后,使用 PostMessage() 或 SendMessageTimeout() 向該窗口發(fā)送 WM_CLOSE 消息。
            2. 使用 WaitForSingleObject() 等待進(jìn)程的句柄。確保你使用超時值等待,因為在很多情況下 WM_CLOSE 不會關(guān)閉應(yīng)用程序。記住,應(yīng)使超時值足夠長(通過 WaitForSingleObject() 或 SendMessageTimeout()),以便用戶可以響應(yīng)為了 處理 WM_CLOSE 消息而創(chuàng)建的任何對話框。
            3. 如果返回值為 WAIT_OBJECT_0,則應(yīng)用程序已干凈地將其自身關(guān)閉。如果返回值為 WAIT_TIMEOUT,則必須使用 TerminateProcess() 關(guān)閉應(yīng)用程序。

              注意:如果從 WaitForSingleObject() 得到的返回值不是 WAIT_OBJECT_0 或 WAIT_TIMEOUT,則應(yīng)使用 GetLastError() 找出原因。
            通過執(zhí)行上述這些步驟,你便完全有可能干凈地關(guān)閉應(yīng)用程序(無需 IPC 或用戶干預(yù))。

            16 位問題(在 Windows NT 下)

              上述步驟適用于 Windows 95 下的 16 位應(yīng)用程序,而 Windows NT 下的 16 位應(yīng)用程序與 Windows 95 下的 16 位應(yīng)用程序的工作方式差別非常大。
              在 Windows NT 下,所有 16 位應(yīng)用程序都在虛擬 DOS 機(jī) (VDM) 中運行。此 VDM 是作為 Windows NT 下的一個 Win32 進(jìn)程 (NTVDM) 運行的。NTVDM 進(jìn)程具有進(jìn)程 ID。你可以通過 OpenProcess() 獲取該進(jìn)程的句柄,就像處理其它任何 Win32 進(jìn)程一樣。不過,在 VDM 中運行的 16 位應(yīng)用程序都沒有進(jìn)程 ID,因此你無法從 OpenProcess() 獲取進(jìn)程句柄。VDM 中的每個 16 位應(yīng)用程序都有一個 16 位任務(wù)句柄和一個 32 位執(zhí)行線程。可通過調(diào)用函數(shù) VDMEnumTaskWOWEx() 找到該任務(wù)句柄和線程 ID。有關(guān)這方面的其它信息,請參見:“如何用 Win32 APIs 枚舉應(yīng)用程序窗口和進(jìn)程”。
              關(guān)閉 Windows NT 下的 16 位應(yīng)用程序的首選和最直接的方法是關(guān)閉整個 NTVDM 進(jìn)程。你可以通過執(zhí)行前面所描述的步驟來完成此操作。你只需知道 NTVDM 的進(jìn)程 ID 即可,參考“如何用 Win32 APIs 枚舉應(yīng)用程序窗口和進(jìn)程”所講的方法來查找 NTVDM 的進(jìn)程 ID。此方法的缺點是它會關(guān)閉在該 VDM 中運行的所有 16 位應(yīng)用程序。如果這不是你想要的結(jié)果,則需要采取其它方法。
              如果你希望關(guān)閉 NTVDM 進(jìn)程中的單個 16 位應(yīng)用程序,需要按照下列步驟操作:
            1. 向該進(jìn)程所擁有的以及與你要關(guān)閉的 16 位任務(wù)具有相同線程 ID 的所有頂級窗口發(fā)送一條 WM_CLOSE 消息。執(zhí)行此操作最有效的方法是使用 EnumWindows()。在回調(diào)函數(shù)中,檢查窗口的進(jìn)程 ID 和線程 ID 是否與要關(guān)閉的 16 位任務(wù)相匹配。請記住,該進(jìn)程 ID 將成為在其中運行 16 位應(yīng)用程序的 NTVDM 的進(jìn)程 ID。
            2. 盡管你有線程 ID,但無法等待 16 位進(jìn)程的終止。因此,你必須等待任意時間長度(以允許干凈關(guān)閉),然后嘗試關(guān)閉應(yīng)用程序。如果應(yīng)用程序已關(guān)閉,則此操作無效。如果應(yīng)用程序尚未關(guān)閉,則它將終止應(yīng)用程序。
            3. 使用稱為 VDMTerminateTaskWOW() 的函數(shù)終止應(yīng)用程序,該函數(shù)可在 Vdmdbg.dll 中找到。它采用 VDM 的進(jìn)程 ID 和 16 位任務(wù)的任務(wù)編號。

              此方法允許你關(guān)閉 Windows NT 下 VDM 中的單個 16 位應(yīng)用程序。不過,16 位 Windows 以及 VDM 中運行的 WOWExec 都不能有效地清除已終止任務(wù)的資源。如果你要尋找最有可能干凈地終止 Windows NT 下的 16 位應(yīng)用程序的方法,應(yīng)考慮終止整個 VDM 進(jìn)程。注意:如果你要啟動以后可能會終止的 16 位應(yīng)用程序,請將 CREATE_SEPARATE_WOW_VDM 與 CreateProcess() 結(jié)合使用。

            示例代碼

              下面的示例代碼使用以下兩個函數(shù)實現(xiàn)上述用于 16 位和 32 位應(yīng)用程序的方法:TerminateApp() 和 Terminate16App()。TerminateApp() 采用一個 32 位進(jìn)程 ID 和一個超時值(以毫秒為單位)。Terminate16App()。這兩個函數(shù)都使用 DLL 函數(shù)的顯式鏈接,以便它們的二進(jìn)制文件與 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 );



            //*********************

            // 實現(xiàn)代碼 TermApp.cpp

            //*********************

            #include "TermApp.h"

            #include <vdmdbg.h>

            typedef struct

            {

            DWORD dwID ;

            DWORD dwThread ;

            } TERMINFO ;

            // 聲明回調(diào)枚舉函數(shù).

            BOOL CALLBACK TerminateAppEnum( HWND hwnd, LPARAM lParam ) ;

            BOOL CALLBACK Terminate16AppEnum( HWND hwnd, LPARAM lParam ) ;

            /*----------------------------------------------------------------

            DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )

            功能:

            關(guān)閉 32-位進(jìn)程(或 Windows 95 下的 16-位進(jìn)程)

            參數(shù):

            dwPID

            要關(guān)閉之進(jìn)程的進(jìn)程 ID.

            dwTimeout

            進(jìn)程關(guān)閉前等待的毫秒時間.

            返回值:

            TA_FAILED —— 如果關(guān)閉失敗.

            TA_SUCCESS_CLEAN —— 如果使用 WM_CLOSE 關(guān)閉了進(jìn)程.

            TA_SUCCESS_KILL —— 如果使用 TerminateProcess() 關(guān)閉了進(jìn)程.

            返回值的定義參見頭文件.

            ----------------------------------------------------------------*/

            DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout )

            {

            HANDLE hProc ;

            DWORD dwRet ;

            // 如果無法用 PROCESS_TERMINATE 權(quán)限打開進(jìn)程,那么立即放棄。

            hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE,dwPID);

            if(hProc == NULL)

            {
            return TA_FAILED ;
            }


            // TerminateAppEnum() 將 WM_CLOSE 消息發(fā)到所有其進(jìn)程ID 與你所提供的進(jìn)程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 )

            功能:

            關(guān)閉 Win16 應(yīng)用程序.

            參數(shù):

            dwPID

            16-位程序運行其中的 NTVDM 進(jìn)程 ID.

            dwThread

            16-位程序中執(zhí)行線程的線程 ID.

            w16Task

            應(yīng)用程序的 16-位任務(wù)句柄.

            dwTimeout

            任務(wù)關(guān)閉前等待的毫秒時間.



            返回值:

            如果成功, 返回 TA_SUCCESS_16

            如果不成功, 返回 TA_FAILED.

            返回值的定義參見該函數(shù)的頭文件.

            注意:

            你可以通過 VDMEnumTaskWOW() 或 VDMEnumTaskWOWEx() 函數(shù)獲得 Win16 和線程 ID.

            ----------------------------------------------------------------*/

            DWORD WINAPI Terminate16App( DWORD dwPID, DWORD dwThread,

            WORD w16Task, DWORD dwTimeout )

            {

            HINSTANCE hInstLib ;

            TERMINFO info ;

            // 你必須通過外部鏈接調(diào)用函數(shù),以便代碼在所有 Win32 平臺上都兼容。

            BOOL (WINAPI *lpfVDMTerminateTaskWOW)(DWORD dwProcessId,WORD htask) ;

            hInstLib = LoadLibraryA( "VDMDBG.DLL" ) ;

            if( hInstLib == NULL )
            return TA_FAILED ;

            // 獲得函數(shù)過程地址.

            lpfVDMTerminateTaskWOW = (BOOL (WINAPI *)(DWORD, WORD ))

            GetProcAddress( hInstLib, "VDMTerminateTaskWOW" ) ;

            if( lpfVDMTerminateTaskWOW == NULL )

            {

            FreeLibrary( hInstLib ) ;

            return TA_FAILED ;

            }

            // 向所有匹配進(jìn)程 ID 和線程的窗口發(fā)送 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 ;

            }

            posted on 2008-09-22 18:33 深邃者 閱讀(227) 評論(0)  編輯 收藏 引用


            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            久久成人精品| 久久久久久久久久免免费精品 | 久久久久18| 精品久久久久久无码人妻蜜桃| 欧美激情精品久久久久| 亚洲精品乱码久久久久久蜜桃| 一本色道久久99一综合| 亚洲午夜久久影院| 久久久久99精品成人片欧美| 青青草国产成人久久91网| 亚洲国产美女精品久久久久∴| 精品久久久无码人妻中文字幕豆芽| 精品久久久久久亚洲精品| 精品久久亚洲中文无码| 亚洲?V乱码久久精品蜜桃 | 理论片午午伦夜理片久久| 久久一日本道色综合久久| 亚洲精品乱码久久久久久中文字幕 | 97久久久久人妻精品专区| 久久亚洲国产成人影院| 亚洲综合久久夜AV | 无码人妻久久一区二区三区蜜桃| 国产美女久久精品香蕉69| 亚洲AⅤ优女AV综合久久久| 办公室久久精品| 欧美伊香蕉久久综合类网站| 欧美va久久久噜噜噜久久| 久久精品国产AV一区二区三区| 久久久精品视频免费观看| 亚洲国产小视频精品久久久三级| 久久人人爽人人爽人人爽| 色99久久久久高潮综合影院| 久久中文字幕视频、最近更新 | 精品久久久久久中文字幕人妻最新| 精品久久久久久无码不卡| 久久综合久久久| 久久精品一本到99热免费| 亚洲AV无码1区2区久久| 亚洲国产成人久久一区WWW| 久久99国产精品二区不卡| 久久久国产打桩机|