从 Windows x64 中的句柄获取可执行文件名

发布于 2024-08-09 12:46:56 字数 1259 浏览 11 评论 0原文

我有一个编译为 x86 的 ac# 应用程序,因此它在 Windows 7 x64 上作为 32 位应用程序运行。 当应用程序运行时,我需要检测活动窗口的可执行文件名称。 在 Winodws XP 上,以下代码运行良好(从活动窗口句柄获取进程文件名)。 在 x64 上,它仅报告 32 位进程的名称(为其他进程返回垃圾,可能是因为我没有检查返回的数据)。我正在传递通过 GetForegroundWindow API 获得的活动窗口的句柄。

public static string GetProcessPathFromWindowHandle(IntPtr hWnd) {

        string filename = string.Empty;
        uint pid=0;
        Unmanaged.GetWindowThreadProcessId(hWnd, out pid);

        //error in Win64: returns strange characters for Win64 files
        const int nChars = 1024;
        StringBuilder filenameBuffer = new StringBuilder(nChars);
        IntPtr hProcess = Unmanaged.OpenProcess(1040, 0, pid);
        Unmanaged.GetModuleFileNameEx(hProcess, IntPtr.Zero, filenameBuffer, nChars);
        Unmanaged.CloseHandle(hProcess);

        filename = filenameBuffer.ToString();

        //Get the name of the Windows
        int length = Unmanaged.GetWindowTextLength(hWnd);
        StringBuilder sb = new StringBuilder(length + 1);
        Unmanaged.GetWindowText(hWnd, sb, sb.Capacity);

        Logger.Main.LogMessage("Window Title is: " + sb);
        Logger.Main.LogMessage("Process filename is: " + filename);
        return filename;
    }

我可以在 64 位环境中从 32 位进程获取该信息吗?谢谢。 安德里亚

I have a c# application that is compiled as x86 so it runs as a 32bit application on Windows 7 x64.
While the application is running, I need to detect the executable name of the active window.
On Winodws XP the following code worked fine (getting the process filename from the active window handle).
On x64 it reports the name of only the 32bit processes (returning garbage for the others, probably because I'm not checking the data returned). I'm passing the handle of the active window that I got with the GetForegroundWindow API.

public static string GetProcessPathFromWindowHandle(IntPtr hWnd) {

        string filename = string.Empty;
        uint pid=0;
        Unmanaged.GetWindowThreadProcessId(hWnd, out pid);

        //error in Win64: returns strange characters for Win64 files
        const int nChars = 1024;
        StringBuilder filenameBuffer = new StringBuilder(nChars);
        IntPtr hProcess = Unmanaged.OpenProcess(1040, 0, pid);
        Unmanaged.GetModuleFileNameEx(hProcess, IntPtr.Zero, filenameBuffer, nChars);
        Unmanaged.CloseHandle(hProcess);

        filename = filenameBuffer.ToString();

        //Get the name of the Windows
        int length = Unmanaged.GetWindowTextLength(hWnd);
        StringBuilder sb = new StringBuilder(length + 1);
        Unmanaged.GetWindowText(hWnd, sb, sb.Capacity);

        Logger.Main.LogMessage("Window Title is: " + sb);
        Logger.Main.LogMessage("Process filename is: " + filename);
        return filename;
    }

Can I get that piece of information form a 32bit process in a 64bit environment? Thanks.
Andrea

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

瞳孔里扚悲伤 2024-08-16 12:46:56

仅供参考,有一个 API GetWindowModuleFileName 可以完成所有操作您只需一次通话即可完成。我还没有检查它在你的场景中是否效果更好。

FYI, there's an API GetWindowModuleFileName that does all you want in a single call. I haven't checked if it works any better in your scenario though.

向地狱狂奔 2024-08-16 12:46:56

由于没有错误检查:您是否已单步执行代码并验证 GetModuleFileNameEx 之前的各种 API 调用是否返回合理的信息?另外,您应该定义一些符号常量,而不是对 1040 访问说明符进行硬编码。

您是否尝试过使用 System.Diagnostics.Process.GetProcessById() ?它有一个 MainModule 属性,您可以从中获取 FileName。不过值得一试。

不过,一些粗略的谷歌搜索表明您可能会陷入 x64 与 WoW64 的困境。其中一个更有用的搜索结果是这个 -摘要:查看 QueryFullProcessImageName

编辑:

显然 WMI 可以弥补 WoW64 的差距,允许您执行SELECT ExecutablePath FROM Win32_Process WHERE ProcessID = %ProcessID%。根据我的经验,WMI 有点重,所以这将是最后的手段。

Since there's no error checking: have you stepped through the code and verified that the various API calls before GetModuleFileNameEx return sensible information? Also, you should define some symbolic constats instead of hardcoding the 1040 access specifier.

Have you tried using System.Diagnostics.Process.GetProcessById()? It has a MainModule property from where you can grab FileName. Worth a shot, though.

Some cursory googling indicates you might be running your head into x64 vs. WoW64 walls, though. One of those more useful search results was this - summary: check out QueryFullProcessImageName.

EDIT:

Apparently WMI can bridge the WoW64 gap, allowing you to do SELECT ExecutablePath FROM Win32_Process WHERE ProcessID = %ProcessID%. In my experience WMI is somewhat heavy, so it would be a last resort.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文