代码之家  ›  专栏  ›  技术社区  ›  Pretzel

如果我只有一个窗口句柄(hwnd),如何获取modulefilename()?

  •  10
  • Pretzel  · 技术社区  · 17 年前

    我正在尝试获取我的C 2.0应用程序之外的窗口的可执行文件的名称。我的应用程序当前使用“user32.dll”中的getForegroundWindow()调用获取窗口句柄(hwnd)。

    从我所能做的挖掘来看,我想使用getModuleFileNameEx()函数(从psapi)获取名称,但getModuleFileNameEx()需要进程的句柄,而不是窗口。

    是否可以从窗口句柄获取进程句柄?(是否需要先获取窗口的线程句柄?)

    编辑了第一句话,让它更清楚地表明我在做什么。

    更新! 这是我发现对我有用的C代码。唯一的警告是 偶尔地 它返回驱动器号为“?”的文件/路径。而不是实际的驱动器号(如“C”)。--还没弄清楚原因。

    [DllImport("user32.dll")]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    
    [DllImport("kernel32.dll")]
    static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);
    
    [DllImport("psapi.dll")]
    static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);
    
    [DllImport("kernel32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(IntPtr hObject);
    
    private string GetWindowModuleFileName(IntPtr hWnd)
    {
        uint processId = 0;
        const int nChars = 1024;
        StringBuilder filename = new StringBuilder(nChars);
        GetWindowThreadProcessId(hWnd, out processId);
        IntPtr hProcess = OpenProcess(1040, 0, processId);
        GetModuleFileNameEx(hProcess,IntPtr.Zero,filename,nChars);
        CloseHandle(hProcess);
        return (filename.ToString());
    }
    
    5 回复  |  直到 15 年前
        1
  •  6
  •   Larry Osterman    17 年前

    你可以打电话 GetWindowThreadProcessId 这将返回与窗口关联的进程。

    从那里,你可以打电话给 OpenProcess 打开进程并获取进程的句柄。

        2
  •  8
  •   wieeeeee    17 年前

    在同一个问题上苦苦挣扎了一个小时,第一个字母也被一个 ? 通过使用GetModuleFileNameEx。 最后使用 系统.诊断.过程 班级。

    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
    
    void GetProcessPathFromWindowHandle(IntPtr hwnd)
    {
       uint pid = 0;
       Win32.GetWindowThreadProcessId(hwnd, out pid);
       Process p = Process.GetProcessById((int)pid);
       return p.MainModule.FileName;
    }
    
        3
  •  2
  •   community wiki Greg Domjan    17 年前

    如果您在Windows 64位平台上运行,则可能需要改用queryfullprocessimagename。这将返回一个用户样式路径,而getprocessImageFileName返回一个系统样式路径,该路径需要使用ntquerysymbolinkObject或zwquerysymbolinkObject进行转换。

    一个庞大的例子功能-建议分成可重复使用的位。

    typedef DWORD (__stdcall *PfnQueryFullProcessImageName)(HANDLE hProcess, DWORD dwFlags, LPTSTR lpImageFileName, PDWORD nSize);
    typedef DWORD (__stdcall *PfnGetModuleFileNameEx)(HANDLE hProcess, HMODULE hModule, LPTSTR lpImageFileName, DWORD nSize);
    
    std::wstring GetExeName( HWND hWnd ){
    // Convert from Window to Process ID
    DWORD dwProcessID = 0;
    ::GetWindowThreadProcessId(hWnd, &dwProcessID);
    
    // Get a handle to the process from the Process ID
    HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);
    
    // Get the process name
    if (NULL != hProcess) {
        TCHAR szEXEName[MAX_PATH*2] = {L'\0'};
        DWORD nExeName = sizeof(szEXEName)/sizeof(TCHAR);
    
        //  the QueryFullProcessImageNameW does not exist on W2K
        HINSTANCE hKernal32dll = LoadLibrary(L"kernel32.dll");
        PfnQueryFullProcessImageName pfnQueryFullProcessImageName = NULL;
        if(hKernal32dll != NULL) {
            pfnQueryFullProcessImageName = (PfnQueryFullProcessImageName)GetProcAddress(hKernal32dll, "QueryFullProcessImageNameW");
            if (pfnQueryFullProcessImageName != NULL) 
                pfnQueryFullProcessImageName(hProcess, 0, szEXEName, &nExeName);
            ::FreeLibrary(hKernal32dll);
        } 
    
        // The following was not working from 32 querying of 64 bit processes
        // Use as backup for when function above is not available 
        if( pfnQueryFullProcessImageName == NULL ){ 
            HINSTANCE hPsapidll = LoadLibrary(L"Psapi.dll");
            PfnGetModuleFileNameEx pfnGetModuleFileNameEx = (PfnGetModuleFileNameEx)GetProcAddress(hPsapidll, "GetModuleFileNameExW");
            if( pfnGetModuleFileNameEx != NULL )    
                pfnGetModuleFileNameEx(hProcess, NULL, szEXEName, sizeof(szEXEName)/sizeof(TCHAR));
            ::FreeLibrary(hPsapidll);
        }
    
        ::CloseHandle(hProcess);
    
        return( szEXEName );
    } 
    return std::wstring();
    }
    
        4
  •  1
  •   Adam Rosenfield    17 年前

    你到底想做什么?您可以获取创建窗口的进程的进程ID GetWindowThreadProcessId() 紧随其后 OpenProcess() 获取进程句柄。但这看起来很笨拙,我觉得有一种更优雅的方式来做你想做的事情。

        5
  •  0
  •   muh    16 年前

    尝试此操作获取可执行文件的文件名:

    C:

    string file = System.Windows.Forms.Application.ExecutablePath;
    

    金属纤维板料