2010-09-08 39 views
0

概括起來講,我需要這樣做:如何在C#/ Win32中獲取正在運行的進程的DOS路徑名?

12345(HWND) - > 「C:\ setup.exe」 文件


現在,我使用GetProcessImageFileName來檢索進程句柄的內核設備路徑。我正在使用OpenProcess檢索句柄,並將PID傳遞給它。 PID(我也需要)正在使用GetWindowThreadProcessId進行檢索。

然而,這讓我像一個字符串:

\設備\ Harddisk1的\ SETUP.EXE

在這一點上,我枚舉系統上的所有驅動器使用DriveInfo.GetDrives(),然後致電QueryDosDevice。最後,我可以做一些字符串操作魔法,「熱潮,」我有我的路。


好了,我的問題:

  1. 這一過程打破了網絡驅動器上。
  2. 我真正想要的是QueryFullProcessImageName在XP

,必須有一個更好的方式來做到這一點。請賜教,WIN32API的神啊!

+0

你/你的進程使枚舉管理權限? – Oleg 2010-09-08 22:46:45

+0

潛在的,沒有。 – 2010-09-08 22:52:38

+0

但是,我只是檢索驅動器名稱。 – 2010-09-08 22:58:29

回答

2

最明顯的問題是,爲什麼你不只是使用QueryFullProcessImageName,如果這就是你想要什麼?你是否需要與較舊版本的Windows兼容?

最接近相當於QueryFullProcessImageName這可在XP可能是GetModuleFileNameEx。我可能會發現QueryFullProcessImageName是否可用,如果可能使用它,否則回落到GetModuleFileNameEx

編輯:儘管GetModuleFileNameEx在爲每個可能的進程檢索可執行文件的名稱時不是100%可靠的,但它至少在相當大的一部分時間內工作。以下是我放在一起的一小段測試代碼:

#include <windows.h> 
#include <psapi.h> 
#include <iterator> 
#include <iostream> 
#include <string> 
#include <map> 

std::string getfilename(DWORD pid) { 
    HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid); 
    static int winver; 
    char path[256]= {0}; 
    DWORD size = sizeof(path); 

    if (winver==0) 
     winver = GetVersion() & 0xf; 

#if WINVER >= 0x600 
    if (winver >= 6)  
     QueryFullProcessImageName(process, 0, path, &size); 
    else 
#endif 
    if (!GetModuleFileNameEx(process, NULL, path, sizeof(path))) 
     strcpy(path, "Unknown"); 
    return std::string(path); 
} 

typedef std::map<DWORD, std::string> win_map; 

namespace std { 
    ostream &operator<<(ostream &os, win_map::value_type const &v) { 
     return os << v.first << ": " << v.second; 
    } 
} 

BOOL CALLBACK show_info(HWND window, LPARAM lParam) { 
    win_map &exes = *(win_map *)lParam; 

    DWORD pid; 
    GetWindowThreadProcessId(window, &pid); 
    exes[pid] = getfilename(pid); 
    return true; 
} 

int main() { 
    win_map exes; 
    EnumWindows(show_info, (LPARAM)&exes); 
    std::copy(exes.begin(), exes.end(), std::ostream_iterator<win_map::value_type>(std::cout, "\n")); 
    return 0; 
} 

快速測試的結果有些有趣。編譯爲32位代碼,使用QueryFullProcessImageName版本發現33個處理與頂層窗口,並且發現名稱爲這些可執行程序31。使用GetModuleFileNameEx的版本也找到了33個進程,但只發現了21個可執行文件的名稱。然而,如果我編譯爲64位代碼,要麼版本發現文件名爲31的33可執行文件(和相同的兩個失敗)。考慮到你看到XP/x64的頻率,這可能沒有多大意義,但是我發現它很有趣。

在任何情況下,即使是最低能力的版本(32位/ GMFNE)也會找到文件名的大約2/3個rds。雖然這當然不是你希望的,但它肯定比沒有好。

+0

QueryFullProcessImageName在XP上不起作用。是的,我需要這個在較老的操作系統上工作。如果支持,我打算使用Vista + api。 – 2010-09-09 02:19:47

+0

哦,'GetModuleFileNameEx'不適用於另一個進程中的模塊。 – 2010-09-09 02:21:36

+0

也適用! 現在,當前的GetVersion()已被棄用。可能我們應該尋找替代函數。 – 2016-02-12 14:59:46

相關問題