• <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)計(jì)

            常用鏈接

            留言簿(2)

            隨筆檔案

            文章檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            如何用 Win32 APIs 枚舉應(yīng)用程序窗口和進(jìn)程

            如何用 Win32 APIs 枚舉應(yīng)用程序窗口和進(jìn)程

            編譯:NorthTibet

            下載源代碼

            摘要

              我們在編寫程序時(shí),常常遇到的一件事情就是要準(zhǔn)確列出系統(tǒng)中所有正在運(yùn)行的程序或者進(jìn)程。Windows 任務(wù)管理器就是這樣的一個(gè)程序。它既能列出運(yùn)行的桌面應(yīng)用程序,又能列出系統(tǒng)中所有運(yùn)行的進(jìn)程。那么,我們在程序中如何實(shí)現(xiàn)這樣的任務(wù)呢?本文下面將詳細(xì)討論這個(gè)問題。


            枚舉頂層(top-level)窗口

              枚舉桌面頂層窗口相對(duì)于枚舉進(jìn)程來說可能要容易一些。枚舉桌面頂層窗口的方法是用 EnumWindows() 函數(shù)。不要用 GetWindow()來創(chuàng)建窗口列表,因?yàn)榇翱谥g復(fù)雜的父子及同胞關(guān)系(Z-Order)容易造成混亂而使得枚舉結(jié)果不準(zhǔn)確。
              EnumWindows()有兩個(gè)參數(shù),一個(gè)是指向回調(diào)函數(shù)的指針,一個(gè)是用戶定義的 LPARAM 值, 針對(duì)每個(gè)桌面窗口(或者頂層窗口)它調(diào)用回調(diào)函數(shù)一次。然后回調(diào)函數(shù)用該窗口句柄做一些處理,比如將它添加到列表中。這個(gè)方法保證枚舉結(jié)果不會(huì)被窗口復(fù)雜的層次關(guān)系搞亂,因此,一旦有了窗口句柄,我們就可以通過 GetWindowText() 得到窗口標(biāo)題。


            枚舉進(jìn)程

              建立系統(tǒng)進(jìn)程列表比枚舉窗口稍微復(fù)雜一些。這主要是因?yàn)樗玫?API 函數(shù)對(duì)于不同的 Win32 操作系統(tǒng)有依賴性。在 Windows 9x、Windows Me、Windows 2000 Professional 以及 Windows XP 中,我們可以用 ToolHelp32 庫中的 APIs 函數(shù)。但是在 Windows NT 里,我們必須用 PSAPI 庫中的 APIs 函數(shù), PSAPI 庫是 SDK 的一部分。本文我們將討論上述所有平臺(tái)中的實(shí)現(xiàn)。附帶的例子程序?qū)?duì)上述庫中的 APIs 進(jìn)行包裝,以便包裝后的函數(shù)能支持所有 Win32 操作系統(tǒng)。


            使用 ToolHelp32 庫枚舉進(jìn)程

              ToolHelp32 庫函數(shù)在 KERNEL32.dll 中,它們都是標(biāo)準(zhǔn)的 API 函數(shù)。但是 Windows NT 4.0 不提供這些函。
              ToolHelp32 庫中有各種各樣的函數(shù)可以用來枚舉系統(tǒng)中的進(jìn)程、線程以及獲取內(nèi)存和模塊信息。其中枚舉進(jìn)程 只需用如下三個(gè)的函數(shù):CreateToolhelp32Snapshot()、Process32First()和 Process32Next()。
              使用 ToolHelp32 函數(shù)的第一步是用 CreateToolhelp32Snapshot() 函數(shù)創(chuàng)建系統(tǒng)信息“快照”。這個(gè)函數(shù)可以讓你選擇存儲(chǔ)在快照中的信息類型。如果你只是對(duì)進(jìn)程信息感興趣,那么只要包含 TH32CS_SNAPPROCESS 標(biāo)志即可。 CreateToolhelp32Snapshot() 函數(shù)返回一個(gè) HANDLE,完成調(diào)用之后,必須將此 HANDLE 傳給 CloseHandle()。
              接下來是調(diào)用一次 Process32First 函數(shù),從快照中獲取進(jìn)程列表,然后重復(fù)調(diào)用 Process32Next,直到函數(shù)返回 FALSE 為止。這樣將遍歷快照中進(jìn)程列表。這兩個(gè)函數(shù)都帶兩個(gè)參數(shù),它們分別是快照句柄和一個(gè)   PROCESSENTRY32 結(jié)構(gòu)。
              調(diào)用完 Process32First 或 Process32Next 之后,PROCESSENTRY32 中將包含系統(tǒng)中某個(gè)進(jìn)程的關(guān)鍵信息。其中進(jìn)程 ID 就存儲(chǔ)在此結(jié)構(gòu)的 th32ProcessID。此 ID 可以被傳給 OpenProcess() API 以獲得該進(jìn)程的句柄。對(duì)應(yīng)的可執(zhí)行文件名及其存放路徑存放在 szExeFile  結(jié)構(gòu)成員中。在該結(jié)構(gòu)中還可以找到其它一些有用的信息。
              注意:在調(diào)用 Process32First() 之前,一定要記住將 PROCESSENTRY32  結(jié)構(gòu)的 dwSize 成員設(shè)置成 sizeof(PROCESSENTRY32)。


            使用 PSAPI 庫枚舉進(jìn)程

              在 Windows NT 中,創(chuàng)建進(jìn)程列表使用 PSAPI 函數(shù),這些函數(shù)在 PSAPI.DLL 中。這個(gè)文件是隨 Platform SDK 一起分發(fā)的,最新版本的 Platform SDK 可以從這里下載

            使用這個(gè)庫所需的 PSAPI.h 和 PSAPI.lib 文件也在該 Platform SDK 中。
              為了使用 PSAPI 庫中的函數(shù),需將 PSAPI.lib 添加到代碼項(xiàng)目中,同時(shí)在所有調(diào)用 PSAPI API 的模塊中包含 PSAPI.h 文件。記住一定要隨可執(zhí)行文件一起分發(fā) PSAPI.DLL,因?yàn)樗浑S Windows NT 一起分發(fā)。你可以點(diǎn)擊這里單獨(dú)下載 PSAPI.DLL 的可分發(fā)版本(不用完全下載 Platform SDK)。
              與 ToolHelp32 一樣,PSAPI 庫也包含各種各樣有用的函數(shù)。由于篇幅所限,本文只討論與枚舉進(jìn)程有關(guān)函數(shù):EnumProcesses()、 EnumProcessModules()、GetModuleFileNameEx()和 GetModuleBaseName()。
              創(chuàng)建進(jìn)程列表的第一步是調(diào)用 EnumProcesses()。該函數(shù)的聲明如下:

            BOOL EnumProcesses( DWORD *lpidProcess, DWORD cb, DWORD *cbNeeded );
              EnumProcesses()帶三個(gè)參數(shù),DWORD 類型的數(shù)組指針 lpidProcess;該數(shù)組的大小尺寸 cb;以及一個(gè)指向 DWORD 的指針 cbNeeded,它接收返回?cái)?shù)據(jù)的長度。DWORD 數(shù)組用于保存當(dāng)前運(yùn)行的進(jìn)程 IDs。cbNeeded 返回?cái)?shù)組所用的內(nèi)存大小。下面算式可以得出返回了多少進(jìn)程:nReturned = cbNeeded / sizeof(DWORD)。
              注意:雖然文檔將返回的 DWORD 命名為“cbNeeded”,實(shí)際上是沒有辦法知道到底要傳多大的數(shù)組的。EnumProcesses()根本不會(huì)在 cbNeeded 中返回一個(gè)大于 cb 參數(shù)傳遞的數(shù)組值。結(jié)果,唯一確保 EnumProcesses()函數(shù)成功的方法是分配一個(gè) DWORD 數(shù)組,并且,如果返回的 cbNeeded 等于 cb,分配一個(gè)較大的數(shù)組,并不停地嘗試直到 cbNeeded 小于 cb
              現(xiàn)在,你獲得了一個(gè)數(shù)組,其元素保存著系統(tǒng)中每個(gè)進(jìn)程的ID。如果你要想獲取進(jìn)程名,那么你必須首先獲取一個(gè)句柄。要想從進(jìn)程 ID 得到句柄,就得調(diào)用 OpenProcess()。
              一旦有了句柄,則需要得到該進(jìn)程的第一個(gè)模塊。為此調(diào)用 EnumProcessModules() API:
            EnumProcessModules( hProcess, &hModule, sizeof(hModule), &cbReturned );
              調(diào)用之后,hModule 變量中保存的將是進(jìn)程中的第一個(gè)模塊。記住進(jìn)程其實(shí)沒有名字,但進(jìn)程的第一個(gè)模塊既是該進(jìn)程的可執(zhí)行模塊。現(xiàn)在你可以用 hModule 中返回的模塊句柄調(diào)用 GetModuleFileNameEx() 或 GetModuleBaseName() API 函數(shù)獲取全路徑名,或者僅僅是進(jìn)程可執(zhí)行模塊名。兩個(gè)函數(shù)均帶四個(gè)參數(shù):進(jìn)程句柄,模塊句柄,返回名字的緩沖指針以及緩沖大小尺寸。
              用 EnumProcesses() API 返回的每一個(gè)進(jìn)程 ID 重復(fù)這個(gè)調(diào)用過程,你便可以創(chuàng)建 Windows NT 的進(jìn)程列表。


            16位進(jìn)程的處理方法

              在 Windows 95,Windows 98 和 Windows ME 中,ToolHelp32 對(duì)待16位程序一視同仁,它們與 Win32 程序一樣有自己的進(jìn)程IDs。但是在 Windows NT,Windows 2000 或 Windows XP 中情況并不是這樣。在這些操作系統(tǒng)中,16位程序運(yùn)行在所謂的 VDM 當(dāng)中(也就是DOS機(jī))。
              為了在 Windows NT,Windows 2000 和 Windows XP 中枚舉16位程序,你必須使用一個(gè)名為 VDMEnumTaskWOWEx()的函數(shù)。在源代碼模塊中必須包含 VDMDBG.h,并且 VDMDBG.lib 文件必須與項(xiàng)目鏈接。這兩個(gè)文件都在 Platform SDK 中。該函數(shù)的聲明如下:
            INT WINAPI VDMEnumTaskWOWEx( DWORD dwProcessId, TASKENUMPROCEX fp,LPARAM lparam );

              此處 dwProcessId 是 NTVDM 中擬枚舉的16位任務(wù)進(jìn)程標(biāo)示符。參數(shù) fp 是回調(diào)枚舉函數(shù)的指針。參數(shù) lparam 是用戶定義的值,它被傳遞到枚舉函數(shù)。枚舉函數(shù)應(yīng)該被定義成如下這樣:

            BOOL WINAPI Enum16( DWORD dwThreadId, 
            WORD hMod16,
            WORD hTask16,
            PSZ pszModName,
            PSZ pszFileName,
            LPARAM lpUserDefined );
              該函數(shù)針對(duì)每個(gè)運(yùn)行在 NTVDM 進(jìn)程中的16位任務(wù)調(diào)用一次,NTVDM 進(jìn)程ID將被傳入 VDMEnumTaskWOWEx()。如果想繼續(xù)枚舉則返回 FALSE,終止枚舉則返回 TRUE。注意這是與 EnumWindows()相對(duì)的。


            關(guān)于代碼

              本文附帶的代碼例子將 PSAPI 和 ToolHelp32 封裝到一個(gè)名為 EnumProcs() 的函數(shù)中。該函數(shù)的工作原理類似 EnumWindows(),有一個(gè)指向回調(diào)函數(shù)的指針,并要對(duì)該函數(shù)進(jìn)行重復(fù)調(diào)用,針對(duì)系統(tǒng)中的每個(gè)進(jìn)程調(diào)用一次。另一個(gè)參數(shù)是用戶定義的 lParam。下面是該函數(shù)的聲明:
            BOOL WINAPI EnumProcs( PROCENUMPROC lpProc, LPARAM lParam );

            使用該函數(shù)時(shí),要象下面這樣聲明回調(diào)函數(shù):

            BOOL CALLBACK Proc( DWORD dw, WORD w16, LPCSTR lpstr, LPARAM lParam );
              參數(shù) dw 包含 ID,“w16”是16位任務(wù)的任務(wù)號(hào),如果為32位進(jìn)程則為0(在 Windows 95 中總是0),參數(shù)lpstr 指向文件名,lParam 是用戶定義的,要被傳入 EnumProcs()。
              EnumProcs() 函數(shù)通過顯示鏈接使用 ToolHelp32 和 PSAPI,而非通常所用的隱式鏈接。之所以要這樣做,主要是為了讓代碼能夠在二進(jìn)制一級(jí)兼容,從可以在所有 Win32 操作系統(tǒng)平臺(tái)上運(yùn)行。

            posted on 2008-09-22 18:34 深邃者 閱讀(223) 評(píng)論(0)  編輯 收藏 引用


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


            国产亚洲欧美成人久久片| 一本大道久久香蕉成人网| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 日韩欧美亚洲国产精品字幕久久久| 久久久久人妻精品一区二区三区 | 99精品伊人久久久大香线蕉| 久久午夜无码鲁丝片秋霞 | 久久99精品久久久久久水蜜桃| 久久综合欧美成人| 99久久精品国产综合一区| 中文字幕久久欲求不满| 成人亚洲欧美久久久久| 国产福利电影一区二区三区久久久久成人精品综合 | 狠狠色婷婷综合天天久久丁香| 狠狠色噜噜狠狠狠狠狠色综合久久| 国产99久久精品一区二区| 国产激情久久久久影院老熟女免费 | 2021国内精品久久久久久影院| 久久人妻无码中文字幕| 潮喷大喷水系列无码久久精品| 久久美女人爽女人爽| 久久国产乱子伦精品免费午夜| 中文成人无码精品久久久不卡| 人妻少妇久久中文字幕| 久久久久99精品成人片试看| 国产精品一久久香蕉产线看| 精品水蜜桃久久久久久久| 国产一区二区久久久| 久久久一本精品99久久精品88| 国产精品岛国久久久久| 久久久久18| 久久亚洲精品成人av无码网站| 99久久精品免费看国产一区二区三区| 欧美久久亚洲精品| 久久久久99精品成人片试看| 久久精品国产亚洲AV不卡| 亚洲午夜久久久久久久久久 | 深夜久久AAAAA级毛片免费看| 国产亚洲欧美精品久久久| 一级做a爰片久久毛片看看| 成人久久久观看免费毛片|