How do I get GetModuleFileName () if I only have a window handle (hWnd)?

I am trying to get the name of a window executable that is outside of my C # 2.0 application. My application is currently receiving a window handle (hWnd) using the GetForegroundWindow () call from "user32.dll".

From the digging that I was able to do, I think I want to use the GetModuleFileNameEx () function (from the PSAPI) to get the name, but GetModuleFileNameEx () requires a process handle, not a window.

Is it possible to get a process handle from a window handle? (Do I need to get a window thread handle first?)

EDIT the first sentence to clarify what I'm trying to do.

UPDATE! Here the C # code I found worked for me. The only warning is that sometimes it returns a file / path where the drive letter is "?" instead of the actual drive letter (for example, "C"). “I have not understood why.”

[DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("kernel32.dll")] static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId); [DllImport("psapi.dll")] static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize); [DllImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool CloseHandle(IntPtr hObject); private string GetWindowModuleFileName(IntPtr hWnd) { uint processId = 0; const int nChars = 1024; StringBuilder filename = new StringBuilder(nChars); GetWindowThreadProcessId(hWnd, out processId); IntPtr hProcess = OpenProcess(1040, 0, processId); GetModuleFileNameEx(hProcess,IntPtr.Zero,filename,nChars); CloseHandle(hProcess); return (filename.ToString()); } 
+10
c # winapi hwnd
Nov 10 '08 at 4:59
source share
5 answers

You can call GetWindowThreadProcessId , and this will return you the process associated with this window.

From there, you can call OpenProcess to open the process and get the process handle.

+6
Nov 10 '08 at 5:09
source share

Fighting the same problem for an hour now also replaced the first letter with ? using GetModuleFileNameEx. Finaly came up with this solution using the System.Diagnostics.Process class.

 [DllImport("user32.dll")] public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); void GetProcessPathFromWindowHandle(IntPtr hwnd) { uint pid = 0; Win32.GetWindowThreadProcessId(hwnd, out pid); Process p = Process.GetProcessById((int)pid); return p.MainModule.FileName; } 
+7
Nov 26 '08 at 16:36
source share

If you are running on a 64-bit Windows platform, you may need to use QueryFullProcessImageName. This returns a custom style path compared to GetProcessImageFileName, which returns the path to the system style that needs to be converted using NtQuerySymbolicLinkObject or ZwQuerySymbolicLinkObject.

One function of the mammoth example is to split it into reusable bits.

 typedef DWORD (__stdcall *PfnQueryFullProcessImageName)(HANDLE hProcess, DWORD dwFlags, LPTSTR lpImageFileName, PDWORD nSize); typedef DWORD (__stdcall *PfnGetModuleFileNameEx)(HANDLE hProcess, HMODULE hModule, LPTSTR lpImageFileName, DWORD nSize); std::wstring GetExeName( HWND hWnd ){ // Convert from Window to Process ID DWORD dwProcessID = 0; ::GetWindowThreadProcessId(hWnd, &dwProcessID); // Get a handle to the process from the Process ID HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID); // Get the process name if (NULL != hProcess) { TCHAR szEXEName[MAX_PATH*2] = {L'\0'}; DWORD nExeName = sizeof(szEXEName)/sizeof(TCHAR); // the QueryFullProcessImageNameW does not exist on W2K HINSTANCE hKernal32dll = LoadLibrary(L"kernel32.dll"); PfnQueryFullProcessImageName pfnQueryFullProcessImageName = NULL; if(hKernal32dll != NULL) { pfnQueryFullProcessImageName = (PfnQueryFullProcessImageName)GetProcAddress(hKernal32dll, "QueryFullProcessImageNameW"); if (pfnQueryFullProcessImageName != NULL) pfnQueryFullProcessImageName(hProcess, 0, szEXEName, &nExeName); ::FreeLibrary(hKernal32dll); } // The following was not working from 32 querying of 64 bit processes // Use as backup for when function above is not available if( pfnQueryFullProcessImageName == NULL ){ HINSTANCE hPsapidll = LoadLibrary(L"Psapi.dll"); PfnGetModuleFileNameEx pfnGetModuleFileNameEx = (PfnGetModuleFileNameEx)GetProcAddress(hPsapidll, "GetModuleFileNameExW"); if( pfnGetModuleFileNameEx != NULL ) pfnGetModuleFileNameEx(hProcess, NULL, szEXEName, sizeof(szEXEName)/sizeof(TCHAR)); ::FreeLibrary(hPsapidll); } ::CloseHandle(hProcess); return( szEXEName ); } return std::wstring(); } 
+2
Feb 11 '09 at 2:38
source share

What exactly are you trying to do? You can get the process ID of the process that created the window with GetWindowThreadProcessId () , followed by OpenProcess () to get the process handle. But it seems very silly, and I feel that there is a more elegant way to do what you want to do.

+1
Nov 10 '08 at 5:10
source share

try this to get the executable file name:

FROM#:

 string file = System.Windows.Forms.Application.ExecutablePath; 

Mfg

0
May 31 '10 at 7:52 a.m.
source share



All Articles