?? 如何獲取某個(gè)進(jìn)程的主窗口以及創(chuàng)建進(jìn)程的程序名?.txt
字號(hào):
如何獲取某個(gè)進(jìn)程的主窗口以及創(chuàng)建進(jìn)程的程序名?
2005年7月15日 星期五
交換機(jī) 動(dòng)畫制作 免費(fèi)空間 電子商務(wù) 筆記本 網(wǎng)站建設(shè) 掌上電腦 虛擬主機(jī) 路由器 中關(guān)村 網(wǎng)頁設(shè)計(jì) 數(shù)據(jù)庫技術(shù)
如何獲取某個(gè)進(jìn)程的主窗口以及創(chuàng)建進(jìn)程的程序名?作者:未知 文章來源:本站原創(chuàng)
如何獲取某個(gè)進(jìn)程的主窗口以及創(chuàng)建進(jìn)程的程序名?
交換機(jī) | 動(dòng)畫制作 | 免費(fèi)空間 | 電子商務(wù) | 筆記本 | 網(wǎng)站建設(shè) | 掌上電腦 | 虛擬主機(jī) | 路由器 | 中關(guān)村 |
網(wǎng)頁設(shè)計(jì) | 數(shù)據(jù)庫技術(shù)
第一時(shí)間提供全球重大新聞
[測試] 三年后你是富翁還是窮光蛋?
[幻燈] 章子怡:理財(cái)?shù)淖罡呔辰? [新聞] 05財(cái)富全球500強(qiáng)出爐
[雜志] 《中國企業(yè)家》:陳天橋的“盒子”
[汽車] 爆笑:芙蓉姐姐被撞之后
[幻燈] 比基尼美女惹火身材秀
[論壇] NBA球星:艾弗森和他的汽車
[生活] 復(fù)旦大二學(xué)生在校經(jīng)營印務(wù)咨詢 一年進(jìn)帳500萬
[國際] 日韓著手調(diào)查背后 誰把國產(chǎn)啤酒“妖魔化”
[論壇] 中國性意識(shí)謀變:性浪潮沖擊廣大普通人民
甲醛 中海油 信用卡 三鹿 走光美女 家居美圖
下載源代碼
在編寫工具程序以及系統(tǒng)管理程序的時(shí)候。常常需要獲取某個(gè)進(jìn)程的主窗口以及創(chuàng)建此進(jìn)程的程序名。獲取主窗口的目的是向窗口發(fā)送各種消息。獲取啟動(dòng)進(jìn)程的程序名可以控制對(duì)進(jìn)程的操作。但是有些進(jìn)程往往有多個(gè)主窗口。你要的是哪一個(gè)主窗口呢?如果你用過Outlook程序,你就會(huì)發(fā)現(xiàn)它有多個(gè)主窗口,一個(gè)窗口列出收件箱和其它文件夾。如果你打開e-mail,便會(huì)有另外一個(gè)窗口顯示信息。它們都是沒有父窗口(或者說宿主窗口)的主窗口。運(yùn)行一下Spy程序,你甚至?xí)l(fā)現(xiàn)它們的窗口類名都相同:rctrl_renwnd32。資源管理器(Explorer.exe)也有不止一個(gè)主窗口。如圖一所示,資源管理器有兩個(gè)主窗口。一般來講,想要獲取主窗口,憑窗口的式樣或類名,你沒有什么辦法知道哪一個(gè)窗口是真正意義上的主窗口。
首先我們討論如何從多個(gè)窗口中獲取主窗口?其實(shí)很容易。利用兩個(gè)API函數(shù)便可以實(shí)現(xiàn)。這兩個(gè)API是 EnumWindows 和
GetWindowThreadProcessId。如果你對(duì)這兩個(gè)函數(shù)不熟悉,不要怕,本文提供了一個(gè)C++類來對(duì)這兩個(gè)API進(jìn)行封裝。這個(gè)類叫
CMainWindowIterator,用它可以枚舉某個(gè)進(jìn)程(已知進(jìn)程ID)的所有主窗口。這正是我們想要的東西。其使用方法如下:
DWORD pid = // 已知某個(gè)進(jìn)程的ID
CMainWindowIterator itw(pid);
for (HWND hwnd = itw.First(); hwnd; hwnd=itw.Next()) {
// do something
}
就這么簡單,CMainWindowIterator派生于一個(gè)更通用的類:CWindowIterator,CWindowIterator負(fù)責(zé)將::EnumWindows函數(shù)打包以隱藏回調(diào)細(xì)節(jié)。它有一個(gè)虛擬函數(shù)OnWindow,你可以在派生類中重寫這個(gè)函數(shù),從而可以用任何方式來枚舉窗口。CMainWindowIterator就是重寫了OnWindow函數(shù),讓它只獲取屬于某個(gè)給定進(jìn)程的主窗口:
// (在構(gòu)造函數(shù)中設(shè)置m_pid)
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;
}這兩個(gè)類的定義如下:(對(duì)應(yīng)的文件是 EnumProc.h 和 EnumProc.cpp)
//////////////////////////////////////////////////////
// 這個(gè)類主要是封裝::EnumWindows,列舉頂層窗口
//
class CWindowIterator {
protected:
HWND* m_hwnds; // 隸屬于某個(gè)進(jìn)程PID窗口句柄數(shù)組
DWORD m_nAlloc; // 數(shù)組大小
DWORD m_count; // 找到的窗口句柄數(shù)
DWORD m_current; // 當(dāng)前的窗口句柄
static BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lp);
// 虛擬枚舉函數(shù)
virtual BOOL OnEnumProc(HWND hwnd);
// 在派生中改寫此函數(shù)來過濾不同種類的窗口
virtual BOOL OnWindow(HWND hwnd) {
return TRUE;
}
public:
CWindowIterator(DWORD nAlloc=1024);
~CWindowIterator();
DWORD GetCount() { return m_count; }
HWND First();
HWND Next() {
return m_hwnds && m_current <m_count ? m_hwnds[m_current++] : NULL;
}
};
////////////////////////////////////
// 列舉某個(gè)進(jìn)程的頂層窗口
//
class CMainWindowIterator : public CWindowIterator {
protected:
DWORD m_pid; // 進(jìn)程ID
virtual BOOL OnWindow(HWND hwnd);
public:
CMainWindowIterator(DWORD pid, DWORD nAlloc=1024);
~CMainWindowIterator();
};圖一是用上述C++類編寫的一個(gè)控制臺(tái)程序lp.exe的輸出畫面。最后兩欄分別是對(duì)應(yīng)進(jìn)程的“窗口句柄”和“類名/窗口標(biāo)題”。其命令行開關(guān)“/ct”表示列出窗口類名(c)和窗口標(biāo)題(t)。
圖一
一般來講,如果隸屬于某個(gè)進(jìn)程的窗口沒有可見的父窗口,那么這個(gè)窗口就可以認(rèn)為是此進(jìn)程的主窗口。對(duì)WS_VISIBLE的檢查很重要,因?yàn)橛行?yīng)用創(chuàng)建多個(gè)不可見的頂層窗口。關(guān)于CMainWindowIterator類的使用細(xì)節(jié)請(qǐng)參見本文的例子源代碼。
接下來我們來討論如何獲取創(chuàng)建進(jìn)程的程序文件名。有人用各種方法嘗試過,比如:GetModuleFileName,GetModuleInstance
和
GetModuleHandle,好像都不行。為什么呢?其實(shí),方法是沒錯(cuò),但調(diào)用這些函數(shù)得到的只是當(dāng)前正在運(yùn)行的這個(gè)進(jìn)程已經(jīng)加載的模塊名(modules),不能用于獲取其它進(jìn)程所加載的模塊。因此,必須想別的辦法,首先要考慮兩種情況,一種是如果你寫的程序在Windows
NT,Windows 2000,Windows
XP環(huán)境運(yùn)行,則可以使用PSAPI,這是一個(gè)Windows操作系統(tǒng)中比較新的DLL,利用其中輸出的API函數(shù)可以獲取進(jìn)程和模塊的詳細(xì)信息。另一種是如果你寫的程序在Windows
9x或者Windows
Me中運(yùn)行,則必須借助于ToolHelp,限于本文的篇幅,我在這里不介紹如何使用ToolHelp,如果你感興趣的話可以參考,MSDN的技術(shù)支持文章Q175030,題目為“如何在Win32中枚舉應(yīng)用程序”。
PSAPI中有一個(gè)函數(shù)是GetModuleFileNameEx。它通過某個(gè)進(jìn)程和模塊句柄作為參數(shù)來獲得模塊名。那么對(duì)于某個(gè)進(jìn)程來說,你怎么知道哪個(gè)模塊是啟動(dòng)進(jìn)程的執(zhí)行文件呢呢?PSAPI中的另一個(gè)函數(shù)EnumProcessModules將某個(gè)進(jìn)程中所有模塊的模塊句柄填充到一個(gè)數(shù)組中。這個(gè)數(shù)組的第一個(gè)元素便是主模塊的句柄,所以你用下面的代碼來得到第一個(gè)HMODULE:
DWORD count;
HMODULE hm[1];
EnumProcessModules(hProcess, hm, 1, &count); 然后調(diào)用GetModuleFileNameEx。
實(shí)際上從前面的圖一中可以看到,在lp.exe程序中我們已經(jīng)實(shí)現(xiàn)了羅列進(jìn)程及其對(duì)應(yīng)的模塊名。程序的實(shí)現(xiàn)細(xì)節(jié)中還用到了PSAPI輸出的API函數(shù)EnumProcesses來枚舉所有運(yùn)行進(jìn)程,為了對(duì)具體的細(xì)節(jié)進(jìn)行封裝,我如法炮制編寫了與CWindowIterator
和CMainWindowIterator類似的兩個(gè)C++類:CProcessIterator 和
CProcessModuleIterator ,它們分別對(duì)EnumProcesses 和EnumProcessModules
API函數(shù)進(jìn)行了封裝。有了這兩個(gè)打包類,一切都變得如此簡單。
CProcessIterator itp;
for (DWORD pid=itp.First(); pid; pid=itp.Next()) {
// 處理每一個(gè)進(jìn)程
}下面是獲取創(chuàng)建進(jìn)程的EXE文件名的方法:
CProcessModuleIterator itm(pid);
HMODULE hModule = itm.First(); // .EXE
TCHAR modname[_MAX_PATH];
GetModuleBaseName(itm.GetProcessHandle(), hModule, modname, _MAX_PATH);
因?yàn)閘p顯示出來的并不是一個(gè)含全路徑的模塊文件名,所以我用另外一個(gè)PSAPI函數(shù)GetModuleBaseName來代替GetModuleFileNameEx從而獲取全路徑名。此外,由于CProcessModuleIterator自己會(huì)打開進(jìn)程枚舉模塊,所以不必調(diào)用OpenProcess。用CProcessModuleIterator::GetProcessHandle可以得到已打開進(jìn)程的句柄。lp程序還用CMainWindowIterator來顯示每個(gè)特定進(jìn)程的所有主窗口。下面是CProcessIterator
和 CProcessModuleIterator的定義:
////////////////////////////////////////////////////////////////////////////////////////
// 進(jìn)程列舉類 -- 列舉出系統(tǒng)中的所有進(jìn)程,但總是跳過第一個(gè)PID=0的進(jìn)程,即空閑進(jìn)程(IDLE)
//
class CProcessIterator {
protected:
DWORD* m_pids; // 包含進(jìn)程IDs的數(shù)祖
DWORD m_count; // 數(shù)組大小
DWORD m_current; // 當(dāng)前數(shù)組項(xiàng)
public:
CProcessIterator();
~CProcessIterator();
DWORD GetCount() { return m_count; }
DWORD First();
DWORD Next() {
return m_pids && m_current <m_count ? m_pids[m_current++] : 0;
}
};
/////////////////////////////////////////////////////////////////
// 列舉某個(gè)進(jìn)程的模塊,第一個(gè)模塊就是創(chuàng)建此進(jìn)程的主exe程序
//
class CProcessModuleIterator {
protected:
HANDLE m_hProcess; // 進(jìn)程句柄
HMODULE* m_hModules; // 模塊句柄數(shù)組
DWORD m_count; // 數(shù)組大小
DWORD m_current; // 當(dāng)前模塊的句柄
public:
CProcessModuleIterator(DWORD pid);
~CProcessModuleIterator();
HANDLE GetProcessHandle() { return m_hProcess; }
DWORD GetCount() { return m_count; }
HMODULE First();
HMODULE Next() {
return m_hProcess && m_current < m_count ? m_hModules[m_current++] : 0;
}
};
文章錄入:知秋一葉 責(zé)任編輯:知秋一葉
上一篇文章: 干干凈凈殺死進(jìn)程
下一篇文章: 共享內(nèi)存封裝類
【字體:小 大】【發(fā)表評(píng)論】【加入收藏】【告訴好友】【打印此文】【關(guān)閉窗口】
拍MV愈想完美愈心寒 劉德華遇山洪急逃命(圖)
被騙3000萬疑為炒作 杭天琪頻繁約會(huì)神秘富商
楊千嬅變38D“大胸” 穿超短裙戲院示眾(圖)
看女F4前面波濤洶涌 背景大有來頭 中國女籃60-55擊敗奧運(yùn)亞軍澳大利亞[圖]
中國女排兩連敗 陳忠和微笑無法承受之重
跳遠(yuǎn)名將全裸拍寫真 賽車女郎完美身段
莎娃性感出擊 艷光蓋過花花公子兔女郎[圖]
古月 寫真 韓劇 走光 史密斯夫婦 姚明年 世界大戰(zhàn) 六月影訊 大話體壇 體育貼圖 減肥論壇
北京2008 足球 NBA 電游
網(wǎng)友評(píng)論:(只顯示最新10條。評(píng)論內(nèi)容只代表網(wǎng)友觀點(diǎn),與本站立場無關(guān)!)
沒有任何評(píng)論
相關(guān)文章列表
VBA:輕松定制ERP
VB.NET的數(shù)據(jù)庫基礎(chǔ)編程 (2)
用VB.Net編寫通用報(bào)表組件 (5
用VB.Net編寫通用報(bào)表組件 (4
用VB.Net編寫通用報(bào)表組件 (3
用VB.Net編寫通用報(bào)表組件 (2
用VB.Net編寫通用報(bào)表組件 (1
VB.NET的數(shù)據(jù)庫基礎(chǔ)編程 (1)
用VB.NET來做個(gè)性化瀏覽器
使用VB創(chuàng)建服務(wù)器端組件
最新熱門文章
安全路由器組網(wǎng)及IPSec技術(shù)介紹
布線應(yīng)注意的十個(gè)問題(二)
布線應(yīng)注意的十個(gè)問題(一)
中小學(xué)校園網(wǎng)方案推薦
家庭無線網(wǎng)絡(luò)
ISDN路由器連入中小型網(wǎng)
橫縱開合摩托羅拉MPx專區(qū)驚天問
配置和維護(hù)ApacheWEBServer
關(guān)于Apache服務(wù)器配置技巧
Apache與Tomcat安裝配置手冊(cè)
最新推薦文章
熱門技巧天天遞招 98篇(二十六
[組圖]FREEHAND實(shí)例——繪制足
[組圖]Illustrator漸變網(wǎng)格入門
[組圖]Adobe Illustrator 封套
[組圖]Adobe Illustrator 10的
[組圖]Adobe Illustrator中的簡
[組圖]Adobe Illustrator 9.0
[組圖]3D/VR游戲制作軟件GameS
[組圖]Anark教程:使3D對(duì)象看起
[組圖]3Dmax4的Cult3D輸出插件
| 設(shè)為首頁 | 加入收藏 | 聯(lián)系站長 | 友情鏈接 | 版權(quán)申明 |
Copyright © 2005 100j.net . All Rights Reserved
百極網(wǎng) 版權(quán)所有 desperado@100j.net 廣告聯(lián)系:QQ 67453010
本站所有資源均來自互聯(lián)網(wǎng),如有侵犯您的版權(quán)或其他問題,請(qǐng)通知管理員,我們會(huì)盡快處理!
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -