C++ 如何获取窗口的可执行文件名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2397578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the Executable name of a window
提问by Jaguar
I try to get the name of executable name of all of my launched windows and my problem is that:
我尝试获取所有已启动窗口的可执行文件名称,我的问题是:
I use the method
我用的方法
UINT GetWindowModuleFileName(
HWND hwnd,
LPTSTR lpszFileName,
UINT cchFileNameMax);
And I don't understand why it doesn't work.
我不明白为什么它不起作用。
Data which I have about a window are:
-HWND AND PROCESSID
我有一个窗口的数据是:
-HWND 和 PROCESSID
The error is: e.g:
错误是:例如:
HWND: 00170628
ProcessId: 2336
WindowTitle: C:\test.cpp - Notepad++
GetWindowModuleFileName(): C:\test.exe
HWND: 00172138
ProcessId: 2543
WindowTitle: Firefox
GetWindowModuleFileName(): C:\test.exe
HWND: 00120358
ProcessId: 2436
WindowTitle: Mozilla Thunderbird
GetWindowModuleFileName(): C:\test.exe
Note: test.exe is the name of my executable file, but it is not the fullpath of Notepad++... and it make this for Mozilla Thunderbird too... I don't understand why
注意:test.exe 是我的可执行文件的名称,但它不是 Notepad++ 的完整路径......它也为 Mozilla Thunderbird 做了这个......我不明白为什么
I use the function like this:
我使用这样的功能:
char filenameBuffer[4000];
if (GetWindowModuleFileName(hWnd, filenameBuffer, 4000) > 0)
{
std::cout << "GetWindowModuleFileName(): " << filenameBuffer << std::endl;
}
Thank you for your response.
谢谢您的答复。
回答by avakar
The GetWindowModuleFileName
function works for windows in the current process only.
该GetWindowModuleFileName
函数仅适用于当前进程中的窗口。
You have to do the following:
您必须执行以下操作:
- Retrieve the window's process with
GetWindowThreadProcessId
. - Open the process with
PROCESS_QUERY_INFORMATION
andPROCESS_VM_READ
access rights usingOpenProcess
. - Use
GetModuleFileNameEx
on the process handle.
- 使用 检索窗口的进程
GetWindowThreadProcessId
。 - 使用
PROCESS_QUERY_INFORMATION
和PROCESS_VM_READ
访问权限打开进程OpenProcess
。 - 使用
GetModuleFileNameEx
的进程句柄。
If you really want to obtain the name of the module with which the window is registered (as opposed to the process executable), you can obtain the module handle with GetWindowLongPtr
with GWLP_HINSTANCE
. The module handle can then be passed to the aforementioned GetModuleFileNameEx
.
如果你真的想获得与该窗口登记(而不是过程可执行文件)模块的名称,你可以用获得的模块句柄GetWindowLongPtr
用GWLP_HINSTANCE
。然后可以将模块句柄传递给上述GetModuleFileNameEx
.
Example:
例子:
TCHAR buffer[MAX_PATH] = {0};
DWORD dwProcId = 0;
GetWindowThreadProcessId(hWnd, &dwProcId);
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ , FALSE, dwProcId);
GetModuleFileName((HMODULE)hProc, buffer, MAX_PATH);
CloseHandle(hProc);
回答by Jaguar
Aaah. I read the MSDN page at the bottom.
啊啊。我阅读了底部的 MSDN 页面。
From http://support.microsoft.com/?id=228469
来自http://support.microsoft.com/?id=228469
GetWindowModuleFileName and GetModuleFileName correctly retrieve information ab... GetWindowModuleFileName and GetModuleFileName correctly retrieve information about windows and modules in the calling process. In Windows 95 and 98, they return information about windows and modules in other processes. However, in Windows NT 4.0 and Windows 2000, since module handles are no longer shared by all processes as they were on Windows 95 and 98, these APIs do not return information about windows and modules in other processes.
To get more information on Windows 2000, use the Process Status Helper set of APIs (known as PSAPI, see Psapi.h include file), available since Windows NT 4.0. APIs such as GetModuleFileNameEx and GetModuleBaseName offer equivalent functionality.
GetWindowModuleFileName 和 GetModuleFileName 正确检索信息 ab... GetWindowModuleFileName 和 GetModuleFileName 在调用过程中正确检索有关窗口和模块的信息。在 Windows 95 和 98 中,它们返回有关其他进程中的窗口和模块的信息。但是,在 Windows NT 4.0 和 Windows 2000 中,由于模块句柄不再像在 Windows 95 和 98 上那样由所有进程共享,因此这些 API 不会返回有关其他进程中的窗口和模块的信息。
要获得有关 Windows 2000 的更多信息,请使用自 Windows NT 4.0 起可用的进程状态帮助程序 API 集(称为 PSAPI,请参阅 Psapi.h 包含文件)。诸如 GetModuleFileNameEx 和 GetModuleBaseName 之类的 API 提供了等效的功能。
Try using GetModuleFileNameExinstead.
尝试改用GetModuleFileNameEx。
回答by Logan Capaldo
http://support.microsoft.com/?id=228469
http://support.microsoft.com/?id=228469
The executive summary is, GetWindowModuleFileName doesn't work for windows in other processes in NT based Windows.
执行摘要是,GetWindowModuleFileName 不适用于基于 NT 的 Windows 中其他进程中的窗口。
Instead, you can use QueryFullProcessImageNameonce you have a handle to the process. You can get a handle to the process with OpenProcesswhich you can use once you have a process id. You can get the process id from the HWND by using GetWindowThreadProcessId
相反,您可以在拥有进程句柄后使用QueryFullProcessImageName。您可以使用OpenProcess获取进程的句柄,一旦您拥有进程 ID,就可以使用该句柄。您可以使用GetWindowThreadProcessId从 HWND 获取进程 ID
回答by SturmCoder
This is an example of how get the name of executable that creates window, hope it can give you some ideas about:
这是如何获取创建窗口的可执行文件名称的示例,希望它可以给您一些想法:
while(true)
{
Sleep(250);//reduce cpu usage
CHAR __name[MAX_PATH];//name buffer
HWND hwnd;//window handle
DWORD pid;//process pid
hwnd=FindWindow(NULL,NULL);//find any window
PROCESSENTRY32 entry;//process structure containing info about processes
entry.dwSize=sizeof(PROCESSENTRY32);
HANDLE snapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//get processes
if(hwnd!=0)
{
GetWindowThreadProcessId(hwnd,&pid);//get found window pid
}
if (Process32First(snapshot,&entry)==TRUE)//start listing processes
{
while (Process32Next(snapshot,&entry)==TRUE)
{
if (stricmp(entry.szExeFile,"explorer.exe")==0)
{
if(pid!=entry.th32ProcessID)//if found window pid is explorers one, skip it
{
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);//open processusing PROCESS_ALL_ACCESS to get handle
if(hProcess!=NULL)
{
GetModuleFileNameEx(hProcess,NULL,__name,MAX_PATH);//get executable path
cout<<"Found: "<<__name<<endl;
}
}
}
}
}
To use GetModuleFileNameEx() you probably will need to set linker settings to link library psapi. Also include psapi.h.
要使用 GetModuleFileNameEx(),您可能需要将链接器设置设置为链接库 psapi。还包括 psapi.h。
回答by ChrisF
Well according to the MSDN pagefor GetWindowModuleFileName
you appear to be calling it correctly, and if your executable is located in the the root of C: it is returning the correct value:
好吧,根据MSDN 页面,GetWindowModuleFileName
您似乎正确调用了它,并且如果您的可执行文件位于 C: 的根目录中,它将返回正确的值:
The GetWindowModuleFileName function retrieves the full path and file name of the module associated with the specified window handle.
GetWindowModuleFileName 函数检索与指定窗口句柄关联的模块的完整路径和文件名。
What are you expecting to get back?
你期待什么回来?