在編寫工具程序以及系統管理程序的時候常常需要獲取某_第1頁
在編寫工具程序以及系統管理程序的時候常常需要獲取某_第2頁
在編寫工具程序以及系統管理程序的時候常常需要獲取某_第3頁
在編寫工具程序以及系統管理程序的時候常常需要獲取某_第4頁
在編寫工具程序以及系統管理程序的時候常常需要獲取某_第5頁
已閱讀5頁,還剩1頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、   在編寫工具程序以及系統管理程序的時候。常常需要獲取某個進程的主窗口以及創建此進程的程序名。獲取主窗口的目的是向窗口發送各種消息。獲取啟動進程的程序名可以控制對進程的操作。但是有些進程往往有多個主窗口。你要的是哪一個主窗口呢?如果你用過Outlook程序,你就會發現它有多個主窗口,一個窗口列出收件箱和其它文件夾。如果你打開e-mail,便會有另外一個窗口顯示信息。它們都是沒有父窗口(或者說宿主窗口)的主窗口。運行一下Spy程序,你甚至會發現它們的窗口類名都相同:rctrl_renwnd32。資源管理器(Explorer.exe)也有不止一個主窗口。如圖一所示,資源管理器

2、有兩個主窗口。一般來講,想要獲取主窗口,憑窗口的式樣或類名,你沒有什么辦法知道哪一個窗口是真正意義上的主窗口。首先我們討論如何從多個窗口中獲取主窗口?其實很容易。利用兩個API函數便可以實現。這兩個API是 EnumWindows 和 GetWindowThreadProcessId。如果你對這兩個函數不熟悉,不要怕,本文提供了一個C+類來對這兩個API進行封裝。這個類叫 CMainWindowIterator,用它可以枚舉某個進程(已知進程ID)的所有主窗口。這正是我們想要的東西。其使用方法如下:DWORD pid = / 已知某個進程的IDCMainWindowIterator itw(p

3、id);for (HWND hwnd = itw.First(); hwnd; hwnd=itw.Next() / do something     就這么簡單,CMainWindowIterator派生于一個更通用的類:CWindowIterator,CWindowIterator負責將:EnumWindows函數打包以隱藏回調細節。它有一個虛擬函數OnWindow,你可以在派生類中重寫這個函數,從而可以用任何方式來枚舉窗口。CMainWindowIterator就是重寫了OnWindow函數,讓它只獲取屬于某個給定進程的主窗口: / (在構造函數中設置m_pi

4、d)BOOL CMainWindowIterator:OnWindow(HWND hwnd) if (GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE) DWORD pidwin; GetWindowThreadProcessId(hwnd, &pidwin); if (pidwin=m_pid) return TRUE; return FALSE;這兩個類的定義如下:(對應的文件是 EnumProc.h 和 EnumProc.cpp) / 這個類主要是封裝:EnumWindows,列舉頂層窗口/class CWindowIterator p

5、rotected:HWND*m_hwnds;/ 隸屬于某個進程PID窗口句柄數組DWORD m_nAlloc;/ 數組大小DWORD m_count;/ 找到的窗口句柄數DWORD m_current;/ 當前的窗口句柄static BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lp);/ 虛擬枚舉函數virtual BOOL OnEnumProc(HWND hwnd);/ 在派生中改寫此函數來過濾不同種類的窗口virtual BOOL OnWindow(HWND hwnd) return TRUE;public:CWindowIterator(DWORD

6、nAlloc=1024);CWindowIterator();DWORD GetCount() return m_count; HWND First();HWND Next() return m_hwnds && m_current <m_count ? m_hwndsm_current+ : NULL;/ 列舉某個進程的頂層窗口/class CMainWindowIterator : public CWindowIterator protected:DWORD m_pid;/ 進程IDvirtual BOOL OnWindow(HWND hwnd);public:CMa

7、inWindowIterator(DWORD pid, DWORD nAlloc=1024);CMainWindowIterator();圖一是用上述C+類編寫的一個控制臺程序lp.exe的輸出畫面。最后兩欄分別是對應進程的“窗口句柄”和“類名/窗口標題”。其命令行開關“/ct”表示列出窗口類名(c)和窗口標題(t)。圖一    一般來講,如果隸屬于某個進程的窗口沒有可見的父窗口,那么這個窗口就可以認為是此進程的主窗口。對WS_VISIBLE的檢查很重要,因為有些應用創建多個不可見的頂層窗口。關于CMainWindowIterator類的使用細節請參見本文的例子源

8、代碼。 接下來我們來討論如何獲取創建進程的程序文件名。有人用各種方法嘗試過,比如:GetModuleFileName,GetModuleInstance 和 GetModuleHandle,好像都不行。為什么呢?其實,方法是沒錯,但調用這些函數得到的只是當前正在運行的這個進程已經加載的模塊名(modules),不能用于獲取其它進程所加載的模塊。因此,必須想別的辦法,首先要考慮兩種情況,一種是如果你寫的程序在Windows NT,Windows 2000,Windows XP環境運行,則可以使用PSAPI,這是一個Windows操作系統中比較新的DLL,利用其中輸出的API函數可以獲取進程和模塊

9、的詳細信息。另一種是如果你寫的程序在Windows 9x或者Windows Me中運行,則必須借助于ToolHelp,限于本文的篇幅,我在這里不介紹如何使用ToolHelp,如果你感興趣的話可以參考,MSDN的技術支持文章Q175030,題目為“如何在Win32中枚舉應用程序”。    PSAPI中有一個函數是GetModuleFileNameEx。它通過某個進程和模塊句柄作為參數來獲得模塊名。那么對于某個進程來說,你怎么知道哪個模塊是啟動進程的執行文件呢呢?PSAPI中的另一個函數EnumProcessModules將某個進程中所有模塊的模塊句柄填充到一個數組中

10、。這個數組的第一個元素便是主模塊的句柄,所以你用下面的代碼來得到第一個HMODULE: DWORD count;HMODULE hm1;EnumProcessModules(hProcess, hm, 1, &count); 然后調用GetModuleFileNameEx。實際上從前面的圖一中可以看到,在lp.exe程序中我們已經實現了羅列進程及其對應的模塊名。程序的實現細節中還用到了PSAPI輸出的API函數EnumProcesses來枚舉所有運行進程,為了對具體的細節進行封裝,我如法炮制編寫了與CWindowIterator 和CMainWindowIterator類似的兩個C+類

11、:CProcessIterator 和 CProcessModuleIterator ,它們分別對EnumProcesses 和EnumProcessModules API函數進行了封裝。有了這兩個打包類,一切都變得如此簡單。 CProcessIterator itp;for (DWORD pid=itp.First(); pid; pid=itp.Next() / 處理每一個進程下面是獲取創建進程的EXE文件名的方法: CProcessModuleIterator itm(pid);HMODULE hModule = itm.First(); / .EXETCHAR modname_MAX_

12、PATH;GetModuleBaseName(itm.GetProcessHandle(), hModule, modname, _MAX_PATH);    因為lp顯示出來的并不是一個含全路徑的模塊文件名,所以我用另外一個PSAPI函數GetModuleBaseName來代替GetModuleFileNameEx從而獲取全路徑名。此外,由于CProcessModuleIterator自己會打開進程枚舉模塊,所以不必調用OpenProcess。用CProcessModuleIterator:GetProcessHandle可以得到已打開進程的句柄。lp程序還用C

13、MainWindowIterator來顯示每個特定進程的所有主窗口。下面是CProcessIterator 和 CProcessModuleIterator的定義: / 進程列舉類 - 列舉出系統中的所有進程,但總是跳過第一個PID=0的進程,即空閑進程(IDLE)/class CProcessIterator protected:DWORD*m_pids;/ 包含進程IDs的數祖DWORDm_count;/ 數組大小DWORDm_current;/ 當前數組項public:CProcessIterator();CProcessIterator();DWORD GetCount() retur

14、n m_count; DWORD First();DWORD Next() return m_pids && m_current <m_count ? m_pidsm_current+ : 0;/ 列舉某個進程的模塊,第一個模塊就是創建此進程的主exe程序/class CProcessModuleIterator protected:HANDLEm_hProcess;/ 進程句柄HMODULE*m_hModules;/ 模塊句柄數組DWORDm_count;/ 數組大小DWORDm_current;/ 當前模塊的句柄public:CProcessModuleIterator(DWO

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論