在windows 2000以上的ms作業系統,通過windows的任務管理器可以列出當前系統的所有活動程序(如圖1所示),在windows xp中,更是在控制台下增加了一條tasklist命令,讓系統下的所有程序無所遁行(如圖2所示)。這一切是怎麼實現的呢?
圖 1
圖 2引用侯捷大師在《深入淺出mfc》的一句話,「知其然而不知其所以然,真不是個好辦法」。既然如此,我們乾脆自己動手,自己通過程式設計來實現吧,這樣很有成就感哦!以下所有**均在windows xp sp1+vc6.0 sp6編譯環境下通過。ok,let』 go!
方法二
第二種方法也很常見,通過msdn就可以找到例子**,它是通過psapi.dll提供的api函式enumprocesses和enumprocessmodules來實現。有一點要說明的是,visual studio提供的sdk包裡沒有提供相應的psapi.h和與之相對應的導入庫,筆者當時就很納悶,msdn裡的例子居然編譯不通,後來才發現,編譯時根本找不到「psapi.h」。呵呵,還好,msdn至少告訴我們他們都包含psapi.dll裡,用vc自帶的depend工具一查,果然。這樣就好辦了,我們可以自己找到這些函式入口位址。
小知識:c也好c++也好,一般的函式名本質上都是乙個位址,在win32的api裡,它是指向函式所在dll模組裡函式實現的入口位址。
下面是第二種方法的實現過程:首先,先把psapi.dll裡要用到函式都定義好,方便後面顯示呼叫。
//在psaipi.dll中的函式enumprocesses用來列舉程序
typedef bool (_stdcall *enumprocesses)( //注意這裡要指明呼叫約定為-stdcall
dword* pprocessids, //指向程序id陣列鏈
dword cb, //id陣列的大小,用位元組計數
dword* pbytesreturned); //返回的位元組
//在psapi.dll中的函式enumprocessmodules用來列舉程序模組
typedef bool (_stdcall *enumprocessmodules)(
handle hprocess, //程序控制代碼
hmodule* lphmodule, //指向模組控制代碼陣列鏈
dword cb, //模組控制代碼陣列大小,位元組計數
lpdword lpcbneeded); //儲存所有模組控制代碼所需的位元組數
//在psapi.dll中的函式getmodulefilenameex獲得程序模組名
typedef dword (_stdcall *getmodulefilenameex)(
handle hprocess, //程序控制代碼
hmodule hmodule, //程序控制代碼
lptstr lpfilename, //存放模組全路徑名
dword nsize //lpfilename緩衝區大小,字元計算);
方法三
也許你會說前兩種方法全世界都知道了,沒什麼大不了的!呵呵,那麼筆者現在介紹的第三種方法,你就未必知道了。本方法利用了windows nt/2000下終端服務api函式wtsopenserver()和wtsenumerateprocess()來實現,這兩個函式都定義在wtsapi32.dll裡。具體的關於終端服務方面的知識,大家可以查詢msdn。
首先,我們來顯示申明這兩個函式原形:
typedef handle (_stdcall *wtsopenserver)(
lptstr pservername //netbios指定的終端服務名,如果我們檢視本地終端所有程序資訊我們可以通過在控制台命令列下用nbtstat –an來獲取本機netbios名。如圖3所示。
圖3typedef bool (_stdcall *wtsenumerateprocesses)(
handle hserver, //wtsopenserver返回的控制代碼
dword reserved, //保留值, 0
dword version, //指定列舉要求的版本, 必須為1
pwts_process_info* ppprocessinfo, //這個引數是關鍵,存放我們要的程序名和程序id
dword* pcount //用來存放ppprocessinfo裡wts_process_info結構的數量指標);
通過argv[1]給終端服務名(這裡我們賦本機netbios名)賦乙個值並開啟這項服務:
char* szservername = argv[1];
hwtsserver = pwtsopenserver(szservername);
然後開始遍歷終端伺服器上的所有程序,這裡我們是指本機的所有程序
if(!pwtsenumerateprocesses(hwtsserver,
0,1,
&pwtspi,
&dwcount))
;for(int i=0; i }
怎麼樣,酷吧,跟前面兩種方法效果一樣!
方法四
和方法一方法二一樣,在獲得第一條程序資訊後,開始迴圈遍歷,列出其餘的程序:
while (true)
特別注意的是,這裡system_process_information結構裡程序名的型別為unicode_string, 而unicode_string裡的成員buffer定義的是unicode型別。
typedef struct _system_process_information
system_process_information, *psystem_process_information;
typedef struct _unicode_string unicode_string, *punicode_string;
所以,最後我們要呼叫widechartomultibyte()來還原成ansi字串以便輸出:
widechartomultibyte(cp_acp,
0, psystemprocessinformation->processname.buffer,
psystemprocessinformation->processname.length + 1,
pprocessname,
psystemprocessinformation->processname.length + 1,
null,
null);
具體每個引數大家可以參照msdn,很簡單的。以上四種方法的完整源**見光碟。
從這裡看出,檢視系統當前活動程序的實現也不過如此,況且,筆者還沒有給出第五種方法(可以通過wmi的com介面函式cocreateinstance(),connectserver(),execquery()等函式來實現,留給讀者自己練習),呵呵,好玩吧?居然有那麼多種方法。
寫這篇文章的目的是想告訴大家,有時候通過自己動手,會發現以前認為很nb的東西原來也是很簡單的,只要擅於總結,常動手,我們自己也可以自己打造一些方便好用的小工具來,你說呢?!
(文中涉及**已收錄到雜誌配套光碟「雜誌相關」欄目,按文章名查詢即可)
四種方法實現VC列舉系統當前程序
2005年04月27日 18 03 適合讀者 程式設計師 前置知識 c語言基本閱讀能力 四種方法實現vc列舉系統當前程序 在windows 2000以上的ms作業系統,通過windows的任務管理器可以列出當前系統的所有活動程序 如圖1所示 在windows xp中,更是在控制台下增加了一條task...
四種方法實現VC列舉系統當前程序
四種方法實現vc列舉系統當前程序 在windows 2000以上的ms作業系統,通過windows的任務管理器可以列出當前系統的所有活動程序 如圖1所示 在windows xp中,更是在控制台下增加了一條tasklist命令,讓系統下的所有程序無所遁行 如圖2所示 這一切是怎麼實現的呢?圖 1 圖 ...
VC 中獲取DC的四種方法
一 hdc hdc hdc getdc m hwnd 加兩個冒號表示我們用的是全域性sdk的函式,否則表示我們有的是cwnd中的函式 releasedc m hwnd,hdc 二 cdc pdc getdc releasedc pdc 三 cclientdc dc this 不需要我們去釋放,自己會...