寫一個Windows上的守護進程(8)擷取進程路徑

來源:互聯網
上載者:User

標籤:

寫一個Windows上的守護進程(8)擷取進程路徑

要想守護某個進程,就先得知道這個進程在不在。我們假設要守護的進程只會存在一個執行個體(這也是絕大部分情形)。

我是遍曆系統上的所有進程,然後判斷他們的路徑和要守護的進程是否一致,以此來確定進程是否存在。

遍曆進程大家都知道用CreateToolhelp32Snapshot系列API,但是他們最後取得的是進程exe名稱,不是全路徑,如果僅依靠名稱就可以達到目的也就罷了,但是有的時候還是得取到全路徑,這樣會更靠譜一些。

那麼問題來了,如何取到進程全路徑?

首先登場的是GetModuleFileNameEx。大多數時候,我們都可以用這個函數來取得進程的全路徑,而且這個函數是全平台都有,但是你有沒有注意到這樣一段話:

(來自VS2008的MSDN文檔)

這個函數有缺陷。除了這個問題之外,還有一個問題:如果你是32進程要擷取某個64位進程的全路徑,有可能也會出錯,具體請看我很早前寫過的一片文章http://blog.csdn.net/mkdym/article/details/8688597。

當然微軟也說了,你還可以用GetProcessImageFileName和QueryFullProcessImageName兩個函數呀。

 

那麼接下來說GetProcessImageFileName。這函數確實不存在GetModuleFileNameEx的兩個問題,但是它不支援Windows2000,當然如果你不需要支援Windows2000這種老古董,你完全不用理會這個缺憾。然而,它還有別的問題:

1. 這傢伙返回的是個核心名稱,形如\Device\Harddisk0\Partition1\WINNT\System32\Ctype.nls。核心名稱咱不怕,咱用QueryDosDevice反向擷取:先用QueryDosDevice擷取到所有磁碟的磁碟機名稱和核心名稱的對應關係,然後把剛擷取到的核心名稱的前面部分換掉就可以了。你到網上一搜,也全是這種辦法。

以為這就結束了嗎?請看https://msdn.microsoft.com/en-us/library/windows/desktop/ms683217(v=vs.85).aspx 下面關於動態磁碟的問題,這個問題是我提的:在動態磁碟的情況下,磁碟機的連結會有兩層,這個你可以從Winobj中看到,而QueryDosDevice只能擷取到第一層,GetProcessImageFileName返回的是第二層的!我勒個去!網上一番搜尋之後,許多人給出的答案都是在結果上反覆調用QueryDosDevice,我只能對這些人呵呵,也許他們的電腦比較特殊,QueryDosDevice可以那樣使用。

關於動態磁碟的問題,你還可以看我在上面給出的那個csdn的文章,那是我發現這個問題的過程。

怎麼辦?後來忘了在那個論壇裡邊看到的,用核心功能NtQuerySymbolicLinkObject可以做到QueryDosDevice一樣的事情,經過實驗,這個函數是可以在結果上重複調用的,能夠擷取到最底層的核心名稱。嗯,這個問題就這樣解決了。

當然,一般的機子不會有動態磁碟。

2. 當你看MSDN頁面上我說的“動態磁碟”的問題的時候,應該會注意到,下面有個哥們說,這個函數會返回短路徑名,所以咱也得注意了。把每個返回的路徑都轉換成長路徑名,不管它是不是短路徑名(我也不知道它是不是短路徑名啊)。雖然我測試的時候它返回的都是長路徑名。

這裡還有一點,咱給進程們做了快照了,快照的那一刻磁碟機們是確定的,所以完全不需要擷取每個進程路徑的時候都去擷取所有磁碟機的名稱對應關係,只需要在遍曆開始的時候,準備一下這些名稱,然後遍曆的時候直接拿來用。

嗯,用這個API就是這麼麻煩。

 

最後咱們說QueryFullProcessImageName。這個函數啥都好,就是平台要求太高,得是Vista及以上啊,所以只能是能用則用。

最終我擷取進程路徑的方案是這樣的:如果有QueryFullProcessImageName函數,就用這個函數,沒有的話先上GetModuleFileNameEx,如果GetModuleFileNameEx出錯了再上GetProcessImageFileName。把最麻煩的放到最後。

類名CProcessPathQuery。

大家看代碼的時候可能會注意到,我在處理的時候用了個for迴圈,這是因為我也不知道進程路徑有多長,如果返回錯誤碼說緩衝區不夠,就加長重試,但是也不能無限重試,有個限度。

進程路徑擷取出來之後,因為有可能是GetProcessImageFileName擷取出來的,那就是一個核心名稱,需要轉換,轉換類是CDosPathConverter。

進程遍曆類是CProcessScanner,可以看到我在裡面放了一個CDosPathConverter的執行個體,隨著遍曆類的初始化一起初始化。

遍曆進程的時候需要注意,有幾類特殊的進程我們是擷取不到路徑的,或者擷取他們的路徑是沒有意義的,可以看CProcessPathQuery的注釋。

有一點需要注意,一定要提權,否則就會有好多進程因為我們自己許可權不夠而query失敗。

 

 

源碼:https://git.oschina.net/mkdym/DaemonSvc.git (主)&& https://github.com/mkdym/DaemonSvc.git (提升逼格用的)。

 

 

2015年11月19日星期四

寫一個Windows上的守護進程(8)擷取進程路徑

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.