troubleshooting Question

Application exe file path from application window handle

Avatar of npaun
npaun asked on
Visual Basic Classic
20 Comments1 Solution2969 ViewsLast Modified:
I need a method to get the exe file path (full path, not just the file name) of an application to which belongs the window for which you have hWnd. However, the method must work equally well on 32 and 64-bit systems, and to be reasonably fast, not slower then few milliseconds.

I tried a standard method based on GetModuleFileNameExA (example given), but it doesn’t work on 64bit systems. More precise, it work only for 32 applications, but if the window handle belongs to an 64bit app it will return nothing. This is limitation of the GetModuleFileNameExA, which cannot return information for a 64bit application handle if it is used in a 32bit application. If VB6 could be compiled with 64bit compiler it would work fine, but since there is no 64bit version of VB6…

Also, the method MUST NOT be based on WMI, i.e. something like

    Set Processes = GetObject("winmgmts://localhost")
    Set myProcEnum = Processes.ExecQuery("select * from Win32_Process")

as this usually takes about 50 milliseconds per call, and it is way to slow for my need. I need something based on APIs…

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function OpenProcess Lib "KERNEL32.DLL" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function EnumProcessModules Lib "PSAPI.DLL" (ByVal hProcess As Long, ByRef lphModule As Long, ByVal cb As Long, ByRef cbNeeded As Long) As Long
Private Declare Function GetModuleBaseName Lib "PSAPI.DLL" Alias "GetModuleBaseNameA" (ByVal hProcess As Long, ByVal hModule As Long, ByVal lpFileName As String, ByVal nSize As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function GetModuleFileNameExA Lib "PSAPI.DLL" (ByVal hProcess As Long, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long
Private Declare Function CloseHandle Lib "KERNEL32.DLL" (ByVal Handle As Long) As Long

Private Const MAX_PATH = 260
Private Const PROCESS_VM_READ = 16

Private Sub Command1_Click()
    Dim hWnd As Long
    Dim Path As String, Name As String
    hWnd = FindWindow(vbNullString, "Untitled - Notepad")
    If hWnd = 0 Then
        MsgBox "Notepad is not opened!"
        Exit Sub
    End If
    Path = ExePath(hWnd)
    Debug.Print Path, "|||"
End Sub

Public Function ExePath(ByVal hWnd As Long) As String
    Dim ThreadID As Long, ProcessID As Long
    Dim lngReturn As Long
    Dim strEXEPath As String
    Dim lngSize As Long
    Dim hProcess As Long
    Dim hMod(0 To 1023) As Long
    Dim cbNeeded As Long
    ThreadID = GetWindowThreadProcessId(hWnd, ProcessID)
    lngSize = MAX_PATH
    'Get a handle to the Process
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, ProcessID)

    lngReturn = EnumProcessModules(hProcess, hMod(0), 1024, cbNeeded)
    strEXEPath = String$(lngSize, 0)
    lngReturn = GetModuleFileNameExA(hProcess, hMod(0), strEXEPath, lngSize)
    strEXEPath = Left(strEXEPath, lngReturn)
    lngReturn = CloseHandle(hProcess)
    ExePath = strEXEPath
End Function
Join the community to see this answer!
Join our exclusive community to see this answer & millions of others.
Unlock 1 Answer and 20 Comments.
Join the Community
Learn from the best

Network and collaborate with thousands of CTOs, CISOs, and IT Pros rooting for you and your success.

Andrew Hancock - VMware vExpert
See if this solution works for you by signing up for a 7 day free trial.
Unlock 1 Answer and 20 Comments.
Try for 7 days

”The time we save is the biggest benefit of E-E to our team. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange.

-Mike Kapnisakis, Warner Bros