如何在C#/Win32中获取正在运行的进程的DOS路径名?

如何在C#/Win32中获取正在运行的进程的DOS路径名?,c#,.net,winapi,interop,C#,.net,Winapi,Interop,总而言之,我需要这样做: 12345(hWnd)->“C:\setup.exe” 现在,我正在使用来检索进程句柄的内核设备路径。我正在使用检索句柄,并将PID传递给它。正在使用检索PID(我也需要它) 然而,这让我想到了一个字符串,比如: \设备\Harddisk1\setup.exe 此时,我使用枚举系统上的所有驱动器,然后调用。最后,我可以做一些字符串操作魔术,并且“砰”我有我的路径。 好的,那么我的问题是: 此过程在网络驱动器上发生故障。 我真正想要的是XP 必须有更好的方法来做到这一

总而言之,我需要这样做:

12345(hWnd)->“C:\setup.exe”


现在,我正在使用来检索进程句柄的内核设备路径。我正在使用检索句柄,并将PID传递给它。正在使用检索PID(我也需要它)

然而,这让我想到了一个字符串,比如:

\设备\Harddisk1\setup.exe

此时,我使用枚举系统上的所有驱动器,然后调用。最后,我可以做一些字符串操作魔术,并且“”我有我的路径。
好的,那么我的问题是:

  • 此过程在网络驱动器上发生故障。
  • 我真正想要的是XP

  • 必须有更好的方法来做到这一点。请启发我,哦,WIN32API的神

    一个显而易见的问题是,如果您想要的话,为什么不直接使用
    QueryFullProcessImageName
    ?您需要与旧版本的Windows兼容吗

    XP上可用的与
    QueryFullProcessImageName
    最接近的等价物可能是
    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;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    std::string getfilename(DWORD pid){
    HANDLE process=OpenProcess(process_QUERY_INFORMATION | process_VM_READ,false,pid);
    静态int-winver;
    字符路径[256]={0};
    DWORD大小=sizeof(路径);
    如果(winver==0)
    winver=GetVersion()&0xf;
    #如果WINVER>=0x600
    如果(winver>=6)
    QueryFullProcessImageName(进程、0、路径和大小);
    其他的
    #恩迪夫
    if(!GetModuleFileNameEx(进程,NULL,路径,sizeof(路径)))
    strcpy(路径,“未知”);
    返回std::字符串(路径);
    }
    typedef std::map win_map;
    命名空间std{
    
    ostream&operator一个显而易见的问题是,如果您想要的话,为什么不直接使用
    QueryFullProcessImageName
    ?您需要与旧版本的Windows兼容吗

    XP上可用的与
    QueryFullProcessImageName
    最接近的等价物可能是
    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;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    std::string getfilename(DWORD pid){
    HANDLE process=OpenProcess(process_QUERY_INFORMATION | process_VM_READ,false,pid);
    静态int-winver;
    字符路径[256]={0};
    DWORD大小=sizeof(路径);
    如果(winver==0)
    winver=GetVersion()&0xf;
    #如果WINVER>=0x600
    如果(winver>=6)
    QueryFullProcessImageName(进程、0、路径和大小);
    其他的
    #恩迪夫
    if(!GetModuleFileNameEx(进程,NULL,路径,sizeof(路径)))
    strcpy(路径,“未知”);
    返回std::字符串(路径);
    }
    typedef std::map win_map;
    命名空间std{
    
    ostream&operator必须能够检索运行进程的文件路径,因为Sysinternals的Process Explorer可以检索文件路径。当然,Process Explorer使用,这是不受支持的函数。(另一方面,由于您专门针对XP,并且会在Vista和更高版本上使用
    QueryFullProcessImageName
    ,因此担心API在未来版本的Windows中不可用可能不是一个问题。)


    .

    必须能够检索到运行进程的文件路径,因为Sysinternals的Process Explorer可以检索到该路径。当然,Process Explorer使用,这是不受支持的功能。(另一方面,由于您专门针对XP,并且会在Vista和更高版本上使用
    QueryFullProcessImageName
    ,因此担心API在未来版本的Windows中不可用可能不是一个问题。)


    .

    您/您的进程具有枚举管理权限吗?但是,我只是检索驱动器名。您/您的进程具有枚举管理权限吗?但是,我只是检索驱动器名。QueryFullProcessImageName在XP上不起作用。是的,我需要它在旧操作系统上工作。我计划使用Vista+api(如果受支持的话)。哦,而且
    GetModuleFileNameEx
    不适用于另一个进程中的模块。同样适用!现在是当前的GetVersion()不推荐使用。也许我们应该寻找一个替代函数。@Jean PhilippeMond:QueryFullProcessImageName在XP上不起作用。是的,我需要它在旧的操作系统上工作。如果支持,我计划使用Vista+api。哦,
    GetModuleFileNameEx
    不适用于另一个进程中的模块。同样有效!现在当前GetVersion()已弃用。也许我们应该寻找一个替代函数。@Jean PhilippeMond: