Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Executable Name from Window Handle in NT

Posted on 1999-07-07
Medium Priority
Last Modified: 2012-05-05
Can any tell me how to get the executable name from a window handle running on NT.  The GetWindowHandle and GetModuleFileName API calls do not work with NT as instance handles are not global.  Any ideas antone?
Question by:JeffClarke
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
LVL 13

Expert Comment

ID: 1522476

  Dim iHwnd As Long
  Dim sCaptionName As String
  Dim sExecName As String
  ' Scan thru windows looking for a specific Exe...
  ' The desktop is the highest window
  iHwnd = GetDesktopWindow()

  ' It's first child is the 1st top level window
  iHwnd = GetWindow(iHwnd, GW_CHILD)

  ' Now examine all top level windows
    Get_Window_Details iHwnd, sExecName, sCaptionName
    If UCase$(sExecName) = UCase$(sProgramExe) Then
      '--If no need to look at the caption...
      If Len(sFindInCaption) = 0 Then
        Get_Handle = iHwnd
        Exit Function
      '--else, check out the caption...
        If InStr(sCaptionName, sFindInCaption) > 0 Then
          Get_Handle = iHwnd
          Exit Function
        End If
      End If
    End If

    iHwnd = GetWindow(iHwnd, GW_HWNDNEXT)
  Loop While iHwnd <> 0

  Get_Handle = 0

End Function

Sub Get_Window_Details(iHwnd As Long, sExecName As String, sCaptionName As String)
  Dim iInstance As Long
  Dim iDummy As Long
  Dim sProgramExe As String

  sExecName = String$(256, 0) ' Predefine string length
  'iInstance = GetWindowLong(iHwnd, GWL_HINSTANCE)
  iDummy = GetModuleFileName(iInstance, sExecName, 255)
  sExecName = Get_Base_Name(sExecName)

  '-- get rid of trailing null 0
  'If InStr(sExecName, Chr$(0)) Then sExecName = Left$(sExecName, InStr(sExecName, Chr$(0)) - 1)

  'DKM - added this for window caption
  sCaptionName = String$(256, 0)  'init string space
  iDummy = GetWindowText(iHwnd, sCaptionName, 255)
  If InStr(sCaptionName, Chr$(0)) Then sCaptionName = Left$(sCaptionName, InStr(sCaptionName, Chr$(0)) - 1)

LVL 13

Expert Comment

ID: 1522477
end sub

LVL 10

Expert Comment

ID: 1522478
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Author Comment

ID: 1522479
This solution works for win 95,98 but trajically not for NT as
requested  In NT the instance handles iare not global but are unique to the address space where the application is running.

A way around this that as been suggested but sadly Ii have been unable to achieve is going via the registry using the process thread ID to retrieve performance data (which fortunately contains the process name)

Expert Comment

ID: 1522480
There is a function called GetModuleFileNameExA in psapi.dll. However, it needs a process handle also. If you
have it also, the fuction can help you to get
the executable Name

Public Declare Function GetModuleFileNameExA Lib "psapi.dll" (ByVal hProcess As String, ByVal hModule As Long, ByVal ModuleName As String, ByVal nSize As Long) As Long

also see
LVL 13

Accepted Solution

Mirkwood earned 400 total points
ID: 1522481
Public Declare Function Process32First Lib "kernel32" ( _
   ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Public Declare Function Process32Next Lib "kernel32" ( _
   ByVal hSnapshot As Long, lppe As PROCESSENTRY32) As Long

Public Declare Function CloseHandle Lib "Kernel32.dll" _
   (ByVal Handle As Long) As Long

Public Declare Function OpenProcess Lib "Kernel32.dll" _
  (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, _
      ByVal dwProcId As Long) As Long

Public Declare Function EnumProcesses Lib "psapi.dll" _
   (ByRef lpidProcess As Long, ByVal cb As Long, _
      ByRef cbNeeded As Long) As Long

Public Declare Function GetModuleFileNameExA Lib "psapi.dll" _
   (ByVal hProcess As Long, ByVal hModule As Long, _
      ByVal ModuleName As String, ByVal nSize As Long) As Long

Public Declare Function EnumProcessModules Lib "psapi.dll" _
   (ByVal hProcess As Long, ByRef lphModule As Long, _
      ByVal cb As Long, ByRef cbNeeded As Long) As Long

Public Declare Function CreateToolhelp32Snapshot Lib "kernel32" ( _
   ByVal dwFlags As Long, ByVal th32ProcessID As Long) As Long

Public Declare Function GetVersionExA Lib "kernel32" _
   (lpVersionInformation As OSVERSIONINFO) As Integer
Public Declare Function TerminateProcess Lib "kernel32" _
    (ByVal hProcess As Long, ByVal uExitCode As Long) As Long

   dwSize As Long
   cntUsage As Long
   th32ProcessID As Long           ' This process
   th32DefaultHeapID As Long
   th32ModuleID As Long            ' Associated exe
   cntThreads As Long
   th32ParentProcessID As Long     ' This process's parent process
   pcPriClassBase As Long          ' Base priority of process threads
   dwFlags As Long
   szExeFile As String * 260       ' MAX_PATH
End Type

   dwOSVersionInfoSize As Long
   dwMajorVersion As Long
   dwMinorVersion As Long
   dwBuildNumber As Long
   dwPlatformId As Long           '1 = Windows 95.
                                  '2 = Windows NT

   szCSDVersion As String * 128
End Type

Public Const PROCESS_VM_READ = 16
Public Const MAX_PATH = 260
Public Const SYNCHRONIZE = &H100000
Public Const TH32CS_SNAPPROCESS = &H2&
Public Const hNull = 0

Main code...

Sub MAIN()
        APP_NAME$ = UCase(Trim(Command$))
    Select Case getVersion()
        Case 1 'Windows 95/98
            Dim f As Long, sname As String
            Dim hSnap As Long, proc As PROCESSENTRY32
            Dim lretprocesshandle As Long
            Dim ProcessName95 As String
            Dim InstrRes As Integer
            Dim lret2 As Long
            hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
            If hSnap = hNull Then Exit Sub
            proc.dwSize = Len(proc)
            ' Iterate through the processes
            f = Process32First(hSnap, proc)
            Do While f
                sname = StrZToStr(proc.szExeFile)

                ProcessName95 = APP_NAME$
                sname = Trim$(sname)
                InstrRes = InStr(1, sname, ProcessName95, vbTextCompare)
                If InstrRes > 2 Then
                    lretprocesshandle = OpenProcess(PROCESS_ALL_ACCESS, True, proc.th32ProcessID)
                lret2 = TerminateProcess(lretprocesshandle, 0&)
                End If
                f = Process32Next(hSnap, proc)
        Case 2 'Windows NT
            Dim cb As Long
            Dim cbNeeded As Long
            Dim NumElements As Long
            Dim ProcessIDs() As Long
            Dim cbNeeded2 As Long
            Dim NumElements2 As Long
            Dim Modules(1 To 200) As Long
            Dim lret As Long
            Dim ModuleName As String
            Dim ProcessName As String
            Dim CompString As String
            Dim nSize As Long
            Dim hProcess As Long
            Dim i As Long
            Dim InstrResNT As Integer
            'Get the array containing the process id's for each process object
            cb = 8
            cbNeeded = 96
            Do While cb <= cbNeeded
                cb = cb * 2
                ReDim ProcessIDs(cb / 4) As Long
                lret = EnumProcesses(ProcessIDs(1), cb, cbNeeded)
            NumElements = cbNeeded / 4
            For i = 1 To NumElements
                'Get a handle to the Process
                hProcess = OpenProcess(PROCESS_QUERY_INFORMATION _
                    Or PROCESS_VM_READ Or PROCESS_TERMINATE, 0, ProcessIDs(i))
                'Got a Process handle
                If hProcess <> 0 Then
                    'Get an array of the module handles for the specified
                    lret = EnumProcessModules(hProcess, Modules(1), 200, _
                    'If the Module Array is retrieved, Get the ModuleFileName
                    If lret <> 0 Then
                        ModuleName = Space(MAX_PATH)
                        nSize = 500
                        lret = GetModuleFileNameExA(hProcess, Modules(1), _
                            ModuleName, nSize)
                        ProcessName = APP_NAME$
                        ModuleName = Trim$(ModuleName)
                        InstrResNT = InStr(1, ModuleName, ProcessName, vbTextCompare)
                        If InstrResNT > 2 Then
                            lret = TerminateProcess(hProcess, 0&)
                        End If
                        'List1.AddItem Left(ModuleName, lRet)
                    End If
                End If
                'Close the handle to the process
            lret = CloseHandle(hProcess)
    End Select
End Sub

Support functions called by main routine...

Public Function getVersion() As Long
   Dim osinfo As OSVERSIONINFO
   Dim retvalue As Integer
   osinfo.dwOSVersionInfoSize = 148
   osinfo.szCSDVersion = Space$(128)
   retvalue = GetVersionExA(osinfo)
   getVersion = osinfo.dwPlatformId
End Function

Function StrZToStr(s As String) As String
   StrZToStr = Left$(s, Len(s) - 1)
End Function


Featured Post


Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
Suggested Courses

670 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question