从 Windows x64 中的句柄获取可执行文件名
我有一个编译为 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
仅供参考,有一个 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.
由于没有错误检查:您是否已单步执行代码并验证
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 the1040
access specifier.Have you tried using
System.Diagnostics.Process.GetProcessById()
? It has aMainModule
property from where you can grabFileName
. 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.