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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:20:28  来源:igfitidea点击:

How to get the Executable name of a window

c++windowswinapi

提问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 GetWindowModuleFileNamefunction works for windows in the current process only.

GetWindowModuleFileName函数仅适用于当前进程中的窗口。

You have to do the following:

您必须执行以下操作:

  1. Retrieve the window's process with GetWindowThreadProcessId.
  2. Open the process with PROCESS_QUERY_INFORMATIONand PROCESS_VM_READaccess rights using OpenProcess.
  3. Use GetModuleFileNameExon the process handle.
  1. 使用 检索窗口的进程GetWindowThreadProcessId
  2. 使用PROCESS_QUERY_INFORMATIONPROCESS_VM_READ访问权限打开进程OpenProcess
  3. 使用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 GetWindowLongPtrwith GWLP_HINSTANCE. The module handle can then be passed to the aforementioned GetModuleFileNameEx.

如果你真的想获得与该窗口登记(而不是过程可执行文件)模块的名称,你可以用获得的模块句柄GetWindowLongPtrGWLP_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 GetWindowModuleFileNameyou 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?

你期待什么回来?