【问题标题】:Get path of a known HWND获取已知 HWND 的路径
【发布时间】:2021-11-25 16:38:47
【问题描述】:

我正在尝试制作一个应用程序,该应用程序仅在调用 dll 时才会运行,此时聚焦的窗口与给定的值具有相同的路径。话虽如此,下面的代码将被添加到一个 dll 中,该 dll 将具有一个以路径值作为参数的函数,如果满足条件,则返回 true,否则返回 false。我遇到的问题是我似乎找不到获取焦点窗口路径的方法,以下代码总是返回一个空字符串。而且我不能简单地使用窗口的标题,因为有些应用程序是的,标题是静态的,比如Task Manager,但是还有其他的标题是改变的,比如Windows Explorer 根据用户的位置改变它的标题in. 我需要改变什么?

以下代码仅用作测试,因为稍后这是我需要的基础,我只需在path 变量上添加一个比较,并基于此返回真或假:

#include "Windows.h";
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;

int main() {
    // 2 seconds delay to have time to switch windows
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));

    HWND hWnd = GetForegroundWindow(); 
    int length = GetWindowTextLength(hWnd);
    wchar_t* title = new wchar_t[length];
    GetWindowTextW(hWnd, title, length);

    DWORD id;
    GetWindowThreadProcessId(hWnd, &id); 

    wchar_t* path = new wchar_t[MAX_PATH];
    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
    GetModuleFileNameW((HMODULE)hProc, path, MAX_PATH);
    CloseHandle(hProc);

    wcout << "ID: " << id << " | Title: " << title << " | Path: " << path << endl << endl;
    return 1;
} 

输出示例:ID: 2536 | Title: Task Manage | Path:

【问题讨论】:

  • 您错误地使用了 GetModuleFilename。它返回当前进程中模块的文件名,它采用 HMODULE,而不是 HPROCESS。这不是为了获取有关另一个进程的信息。
  • 你可能想要GetModuleFileNameEx。您可能还会发现 GetProcessImageFileNameQueryFullProcessImageName 很有趣。 (现在 MSDN 文档由于某种原因返回 404,但它仍在 Google 缓存中)
  • 不幸的是,您在其他线程中建议的内容是针对 C# 的,而这和 C++ 都不是我通常使用的,C++ 仅用于当我真正需要在 Java 中无法完成的事情时,并且我需要一个本机功能。现在至于GetModuleFileNameEx,它不允许我使用它,它被标记为undefined
  • QueryFullProcessImageNameA 确实有效,它给了我我想要的东西(对于某些人来说,它确实需要以Admin 运行,例如Task Manager),但是当它出现时我注意到了一个问题对于浏览器,它在那里失败。但我怀疑这是问题所在,因为他们创建了很多实例,而不仅仅是一个说firefox.exeedge.exeGetWindowTextWGetWindowThreadProcessId 仍然适用于浏览器,但不适用于 QueryFullProcessImageNameA

标签: c++ winapi


【解决方案1】:

为了得到我想要的结果,我切换到QueryFullProcessImageName(就像CherryDT建议看一下),但是你必须小心,你需要以Admin权限运行它以获得一些路径像我遇到Task Manager 这样的应用程序,可能是因为它是一个 Windows 应用程序,不确定,如果您需要更多详细信息,您必须对此进行一些研究。这是一个小例子:

#include "Windows.h";
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;

int main() {
    // 2 seconds delay to have time to switch windows
    std::this_thread::sleep_for(std::chrono::milliseconds(2000));

    HWND hWnd = GetForegroundWindow(); 
    int lgth = GetWindowTextLength(hWnd) + 1;
    wchar_t* title = new wchar_t[lgth];
    GetWindowTextW(hWnd, title, lgth);

    DWORD id;
    GetWindowThreadProcessId(hWnd, &id); 

    wchar_t* path = new wchar_t[MAX_PATH];
    DWORD size = MAX_PATH;
    HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, id);
    QueryFullProcessImageNameW(hProc, 0, path, &size);
    CloseHandle(hProc);

    wcout << "ID: " << id << " | Title: " << title << " | Path: " << path << endl << endl;
    return 1;
} 

输出示例:ID: 12580 | Title: Task Manage | Path: C:\Windows\System32\Taskmgr.exe

【讨论】:

  • 我认为您也可以使用W 版本而不是A 版本,并使用wchar_t 而不是char,就像您为标题所做的那样。 (事实上​​,如果您不使用任何后缀,您应该获得 W 版本。)这样,带有 Unicode 字符的路径仍然可以正常工作。
猜你喜欢
  • 2019-10-15
  • 2019-08-03
  • 1970-01-01
  • 2021-12-21
  • 2010-12-17
  • 1970-01-01
  • 2011-06-13
  • 2020-01-05
  • 1970-01-01
相关资源
最近更新 更多