如何获取窗口的可执行文件名
Posted
技术标签:
【中文标题】如何获取窗口的可执行文件名【英文标题】:How to get the Executable name of a window 【发布时间】:2021-10-04 13:08:35 【问题描述】:我尝试获取所有已启动窗口的可执行文件名称,但我的问题是:
我用方法
UINT GetWindowModuleFileName(
HWND hwnd,
LPTSTR lpszFileName,
UINT cchFileNameMax);
我不明白为什么它不起作用。
关于窗口的数据是:-HWND AND PROCESSID
错误是: 例如:
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
注意:test.exe 是我的可执行文件的名称,但它不是 Notepad++ 的完整路径...而且它也适用于 Mozilla Thunderbird... 我不明白为什么
我使用这样的功能:
char filenameBuffer[4000];
if (GetWindowModuleFileName(hWnd, filenameBuffer, 4000) > 0)
std::cout << "GetWindowModuleFileName(): " << filenameBuffer << std::endl;
感谢您的回复。
【问题讨论】:
【参考方案1】:GetWindowModuleFileName
函数仅适用于当前进程中的窗口。
您必须执行以下操作:
-
使用
GetWindowThreadProcessId
检索窗口的进程。
使用OpenProcess
打开具有PROCESS_QUERY_INFORMATION
和PROCESS_VM_READ
访问权限的进程。
在进程句柄上使用GetModuleFileNameEx
。
如果你真的想获取注册窗口的模块的名称(而不是进程可执行文件),你可以通过GetWindowLongPtr
和GWLP_HINSTANCE
获取模块句柄。然后可以将模块句柄传递给前面提到的GetModuleFileNameEx
。
示例:
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);
【讨论】:
msdn.microsoft.com/en-us/library/windows/desktop/… @MartinBa,请注意它带来了对 oleacc.dll 的依赖。 是的。我只是在阅读您的答案,并认为我也会放弃该功能,因为这是我在搜索引擎上的第一次点击。 请注意,PROCESS_VM_READ
要求 SeDebugPrivilege
在用户令牌中存在并启用。
正确的方法!但是,如果您以其他用户身份运行可执行文件并尝试使用“OpenProcess”获取进程名称,则会抛出“拒绝访问”。在这种情况下还有其他方法可以实现这一点吗?【参考方案2】:
啊啊。我阅读了底部的 MSDN 页面。
来自http://support.microsoft.com/?id=228469
GetWindowModuleFileName 和 GetModuleFileName 正确检索 信息... GetWindowModuleFileName 和 GetModuleFileName 正确检索 关于窗口和模块的信息 在调用过程中。在 Windows 95 中 和 98,他们返回有关信息 其他中的窗口和模块 过程。然而,在 Windows NT 4.0 和 Windows 2000,因为模块句柄 不再由所有进程共享 就像在 Windows 95 和 98 上一样, 这些 API 不返回信息 关于其他中的窗口和模块 进程。
获取有关 Windows 的更多信息 2000,使用进程状态助手 一组 API(称为 PSAPI,请参阅 Psapi.h 包含文件),自 视窗 NT 4.0。 API,例如 GetModuleFileNameEx 和 GetModuleBaseName 提供等价物 功能。
尝试改用GetModuleFileNameEx。
【讨论】:
@Ninefingers:谢谢你的帮助!【参考方案3】:http://support.microsoft.com/?id=228469
执行摘要是,GetWindowModuleFileName 不适用于基于 NT 的 Windows 中其他进程中的窗口。
相反,您可以使用QueryFullProcessImageName 处理进程。您可以使用OpenProcess 获取进程的句柄,一旦您拥有进程ID,就可以使用它。您可以使用 GetWindowThreadProcessId 从 HWND 获取进程 ID
【讨论】:
第一个链接不再适用于此。我尝试了几次搜索,但没有成功。【参考方案4】:根据MSDN page 的GetWindowModuleFileName
,您似乎正确地调用了它,并且如果您的可执行文件位于C 的根目录中:它返回正确的值:
GetWindowModuleFileName 函数检索与指定窗口句柄关联的模块的完整路径和文件名。
你希望得到什么?
【讨论】:
@ChrisF: 看看我的例子,我添加了三个程序,分别是记事本、firefox 和 Thunderbird……我的可执行文件名称是这些程序的 text.exe ???是黑暗面的力量吗? @Jaguar - 我不确定发生了什么。 MSDN 页面暗示您可以为任何窗口句柄调用此函数,但它似乎只返回正在运行的程序的模块名称。 @Ninefingers:没错,我尝试获取 firefox.exe,正如您在我的示例中看到的那样,我的 HWND 打印了良好的 WindowTitle,但 GetWindowModuleFileName 函数没有这样做!!!【参考方案5】:这是一个如何获取创建窗口的可执行文件名称的例子,希望它能给你一些想法:
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;
要使用 GetModuleFileNameEx(),您可能需要设置链接器设置以链接库 psapi。还包括 psapi.h。
【讨论】:
+1 到CreateToolhelp32Snapshot
,这是我发现的唯一一种可以轻松返回所有活动进程的 exe 文件名的方法,不像 OpenProcess
通常需要额外的访问权限。以上是关于如何获取窗口的可执行文件名的主要内容,如果未能解决你的问题,请参考以下文章
如何在 linux 系统的可执行文件上设置图标(或 .ico 文件)?
如何在同一部 iPhone 中获取两个不同版本的可执行文件?使用 Xcode
已安装的 Java 程序提交批处理文件但它不执行。从命令窗口执行相同的可执行文件有效