如何获取窗口的可执行文件名称

时间:2010-03-07 19:24:20

标签: c++ windows winapi

我尝试获取所有已启动窗口的可执行文件名称,我的问题是:

我使用方法

UINT GetWindowModuleFileName(      
HWND hwnd,
LPTSTR lpszFileName,
UINT cchFileNameMax);

我不明白为什么它不起作用。

我对一个窗口的数据是:
-HWND AND PROCESSID

错误是: 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

注意:test.exe是我的可执行文件的名称,但它不是Notepad ++的完整路径...而且这也是Mozilla Thunderbird的原因......我不明白为什么

我使用这样的功能:

char filenameBuffer[4000];
if (GetWindowModuleFileName(hWnd, filenameBuffer, 4000) > 0)
{
    std::cout << "GetWindowModuleFileName(): " << filenameBuffer << std::endl;
}

感谢您的回复。

5 个答案:

答案 0 :(得分:19)

GetWindowModuleFileName(...)函数仅适用于当前流程中的窗口。1

您必须执行以下操作:

  1. 使用GetWindowThreadProcessId检索窗口的过程。
  2. 使用OpenProcess打开包含PROCESS_QUERY_INFORMATION和PROCESS_VM_READ访问权限的流程。
  3. 在流程句柄上使用GetModuleFileNameEx
  4. 如果您确实想要获取用于注册窗口的模块的名称(而不是进程可执行文件),则可以使用带有GWLP_HINSTANCE的GetWindowLongPtr获取模块句柄。然后可以将模块句柄传递给前面提到的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);
    

答案 1 :(得分:3)

啊哈。我在底部阅读了MSDN页面。

来自http://support.microsoft.com/?id=228469

  

GetWindowModuleFileName和   GetModuleFileName正确检索   信息ab ...   GetWindowModuleFileName和   GetModuleFileName正确检索   有关窗口和模块的信息   在调用过程中。在Windows 95中   和98,他们返回有关的信息   窗户和其他模块   流程。但是,在Windows NT 4.0中   和Windows 2000,因为模块处理   不再由所有进程共享   因为他们在Windows 95和98上,   这些API不返回信息   关于其他的窗户和模块   过程

     

获取有关Windows的更多信息   2000年,使用Process Status Helper   一组API(称为PSAPI,请参阅   Psapi.h包含文件),可用   Windows NT 4.0。 API等   GetModuleFileNameEx和   GetModuleBaseName提供等价物   功能。

请尝试使用GetModuleFileNameEx

答案 2 :(得分:2)

http://support.microsoft.com/?id=228469

执行摘要是,GetWindowModuleFileName不适用于基于NT的Windows中其他进程中的窗口。

相反,一旦掌握了流程,就可以使用QueryFullProcessImageName。您可以使用OpenProcess获取流程句柄,一旦您拥有流程ID,就可以使用该句柄。您可以使用GetWindowThreadProcessId

从HWND获取进程ID

答案 3 :(得分:1)

根据GetWindowModuleFileName {{1}}您似乎正确调用它,如果您的可执行文件位于C的根目录中,它将返回正确的值:

  

GetWindowModuleFileName函数检索与指定窗口句柄关联的模块的完整路径和文件名。

你有什么期望回来的?

答案 4 :(得分:1)

这是一个如何获取创建窗口的可执行文件名称的示例,希望它可以为您提供一些想法:

    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。