Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Visual Basic: Общие вопросы > Узнать hWnd, зная имя EXE-файла приложения


Автор: salieri 21.04.20, 11:04
Доброго времени суток!

Запущен процесс "MsgLab.exe". Необходимо найти его hWnd и показать его, так как он свёрнут.
Подскажите, пожалуйста, что я не так делаю в коде?

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Option Explicit
     
    Const TH32CS_SNAPHEAPLIST = &H1
    Const TH32CS_SNAPPROCESS = &H2
    Const TH32CS_SNAPTHREAD = &H4
    Const TH32CS_SNAPMODULE = &H8
    Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)
    Const TH32CS_INHERIT = &H80000000
    Const MAX_PATH As Integer = 260
     
    Private Type PROCESSENTRY32
      dwSize As Long
      cntUsage As Long
      th32ProcessID As Long
      th32DefaultHeapID As Long
      th32ModuleID As Long
      cntThreads As Long
      th32ParentProcessID As Long
      pcPriClassBase As Long
      dwFlags As Long
      szExeFile As String * MAX_PATH
    End Type
     
    Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal lFlags As Long, ByVal lProcessID As Long) As Long
    Private Declare Function Process32First Lib "kernel32" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
    Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    Private Declare Sub CloseHandle Lib "kernel32" (ByVal hPass As Long)
     
    Const SW_NORMAL = 1
    Const SW_MAXIMIZE = 3
    Const SW_MINIMIZE = 6
     
    Private Declare Function SetForegroundWindow Lib "user32" (ByVal hwnd As Long) As Long
    Private Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
    Private Declare Function SetActiveWindow Lib "user32" (ByVal hwnd As Long) As Long
     
    Private Function GetWndProcess(ByVal name_proc As String) As Long
     
    Dim hSnapShot As Long
    Dim uProcess As PROCESSENTRY32
    Dim r As Long
    Dim ProcessName As String
     
    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0&)
    uProcess.dwSize = Len(uProcess)
    r = Process32First(hSnapShot, uProcess)
     
     
    Do While r
     
      ProcessName = Left$(uProcess.szExeFile, IIf(InStr(uProcess.szExeFile, Chr$(0)) > 0, InStr(uProcess.szExeFile, Chr$(0)) - 1, 0))
     
      If ProcessName = name_proc Then
        GetWndProcess = OpenProcess(&H1, False, uProcess.th32ProcessID)
        Exit Do
      End If
      
      r = Process32Next(hSnapShot, uProcess)
     
    Loop
     
    CloseHandle hSnapShot
     
    End Function
     
     
    Private Sub Form_Load()
     
    Dim hWnd_app As Long
     
    hWnd_app = GetWndProcess("MsgLab.exe")
    ShowWindow hWnd_app, SW_NORMAL
     
    CloseHandle hWnd_app
     
    End Sub

Автор: salieri 21.04.20, 20:38
Получилось таким образом вывести сразу несколько hWnd одного окна "MsgLab.exe", а нужен только 1, который именно отвечал бы за окно! Как его выделить из общего списка hWnd (там их у меня 4 штуки вывелось)?

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Public Function EnumWindows() As String()
        Dim r As Long
        Dim pArr() As String
        Dim count As Long
        Dim hwnd As Long
        
        Dim sss As String
        
        Dim vvv As String
        
        Dim sSave As String
        Dim Ret As Long
        
        Dim mv As Long
        
        Dim sw_found As LogVar
        Dim ccc() As String
        
        Dim ddd() As String
        
        sw_found = 0
        
        vvv = "MsgLab.exe"
        
          Dim hWndChildProcessID As Long
        
        r = GetWindow(GetDesktopWindow, GW_CHILD)
        
        
        Do While r
        
                sss = GetExeFromHandle(r)
                
                          
                If sss = vvv Then
        
              Add_Array ccc, r: sw_found = 1
                ElseIf sss <> vvv And sw_found = 1 Then Exit Do
                End If
            
            DoEvents
            count = count + 1
            r = GetWindow(r, GW_HWNDNEXT)
            
            
        Loop
     
        EnumWindows = ccc
    End Function
     
     
    Public Function GetExeFromHandle(hwnd As Long) As String
    Dim threadID As Long, processID As Long, hSnapshot As Long
    Dim uProcess As PROCESSENTRY32, rProcessFound As Long
    Dim i As Integer, szExename As String
        threadID = GetWindowThreadProcessId(hwnd, processID)
        If threadID = 0 Or processID = 0 Then Exit Function
        hSnapshot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0&)
        If hSnapshot = -1 Then Exit Function
        uProcess.dwSize = Len(uProcess)
        rProcessFound = ProcessFirst(hSnapshot, uProcess)
        Do While rProcessFound
            If uProcess.th32ProcessID = processID Then
                i = InStr(1, uProcess.szExeFile, Chr(0))
                If i > 0 Then szExename = Left$(uProcess.szExeFile, i - 1)
                Exit Do
            Else
                rProcessFound = ProcessNext(hSnapshot, uProcess)
            End If
        Loop
        Call CloseHandle(hSnapshot)
        GetExeFromHandle = szExename
    End Function

Автор: salieri 22.04.20, 22:42
Нашёл хороший пример (прикрепил во вложении).
Ещё нашёл несколько примеров в интернете.
Из них скомпоновал такие функции.
API констант или функций, типов может не хватать, вырезал из рабочей программы.
Основные функции постарался учесть.

Всем спасибо за внимание. ;)

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Option Explicit
     
    Public Name_EXE As String
    Public hWnd_list() As String
     
     
     
    Public Const GW_CHILD = 5
    Public Const GW_HWNDNEXT = 2
     
     
     
    Public Const TH32CS_SNAPHEAPLIST = &H1
    Public Const TH32CS_SNAPPROCESS = &H2
    Public Const TH32CS_SNAPTHREAD = &H4
    Public Const TH32CS_SNAPMODULE = &H8
    Public Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)
    Const TH32CS_INHERIT = &H80000000
    Const MAX_PATH As Integer = 260
     
    Public Type PROCESSENTRY32
      dwSize As Long
      cntUsage As Long
      th32ProcessID As Long
      th32DefaultHeapID As Long
      th32ModuleID As Long
      cntThreads As Long
      th32ParentProcessID As Long
      pcPriClassBase As Long
      dwFlags As Long
      szExeFile As String * MAX_PATH
    End Type
     
     Public Declare Function CreateToolhelpSnapshot Lib "kernel32" Alias "CreateToolhelp32Snapshot" (ByVal lFlgas As Long, ByVal lProcessID As Long) As Long
    Public Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
    Public Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
    Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    Public Declare Sub CloseHandle Lib "kernel32" (ByVal hPass As Long)
    Public Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
     
     
    Public Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean
     
    Public Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
    Public Declare Function GetDesktopWindow Lib "user32" () As Long
    Public Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
    Public Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
     
     Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
    Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
     
     
     
    Public Function hWndFromEXE(ByVal str_name_EXE As String) As Long
     
    Name_EXE = str_name_EXE
     
    EnumWindows AddressOf EnumWindowsProc, ByVal 0&
     
    hWndFromEXE = Val(hWnd_list(0))
     
    End Function
     
     
     
     
    Public Function hWndFromInvisibleEXE(ByVal str_name_EXE As String) As Long ' String()
     
    Dim r As Long
    Dim m As Long
     
    Dim sss As String
     
    Dim sSave As String
    Dim Ret As Long
     
     
    Dim sw_found As LogVar
    Dim ccc() As String
     
    sw_found = 0
     
     
    r = GetWindow(GetDesktopWindow, GW_CHILD)
     
     
    Do While r
     
    sss = GetExeFromHandle(r)
     
     
    Ret = GetWindowTextLength(r)
    sSave = Space(Ret)
    GetWindowText r, sSave, Ret + 1
     
    If sss = str_name_EXE Then
     
    sw_found = 1
     
    Add_Array ccc, r ' моя ф-я добавления в массив ccc строки r, она не показана тут
     
    m = IsWindowVisible(r)
     
    If m = 0 Then hWndFromInvisibleEXE = r
     
    ElseIf sss <> str_name_EXE And sw_found = 1 Then Exit Do
     
    End If
     
     
     
    DoEvents
    r = GetWindow(r, GW_HWNDNEXT)
     
    Loop
        
     
    End Function
     
     
     
    Public Function GetExeFromHandle(ByVal h_hwnd As Long) As String
     
    Dim threadID As Long
    Dim processID As Long
    Dim hSnapshot As Long
     
    Dim uProcess As PROCESSENTRY32
    Dim rProcessFound As Long
     
    Dim i As Integer
    Dim szExename As String
        
        
        threadID = GetWindowThreadProcessId(h_hwnd, processID)
        If threadID = 0 Or processID = 0 Then Exit Function
        
        hSnapshot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0&)
        If hSnapshot = -1 Then Exit Function
        
        uProcess.dwSize = Len(uProcess)
        rProcessFound = Process32First(hSnapshot, uProcess)
        
        
        Do While rProcessFound
            
            If uProcess.th32ProcessID = processID Then
                i = InStr(1, uProcess.szExeFile, Chr(0))
                If i > 0 Then szExename = Left$(uProcess.szExeFile, i - 1)
                Exit Do
            Else
                rProcessFound = Process32Next(hSnapshot, uProcess)
            End If
        
        Loop
        
        
        Call CloseHandle(hSnapshot)
        
        GetExeFromHandle = szExename
        
        
    End Function
     
     
    Public Function EnumWindowsProc(ByVal hwnd As Long, ByVal lParam As Long) As Boolean
     
     
    EnumWindowsProc = True
     
     
    If GetExeFromHandle(hwnd) = Name_EXE Then Add_Array hWnd_list, hwnd ' моя ф-я добавления в массив hWnd_list строки hwnd, она не показана тут
     
     
    End Function

GetHwnd.rar (, : 174)

Автор: Black Star 24.04.20, 19:08
А обычным FindWindow нельзя окно найти?

Автор: salieri 13.05.20, 20:14
Black Star, если известен заголовок, то можно, а если известно только имя *.EXE файла? я не знаю, если честно

Автор: B.V. 24.05.20, 04:37
Цитата salieri @
если известно только имя *.EXE файла?

Перебор процессов и перебор потоков, после -- перебор окон в каждом отдельном потоке средствами EnumThreadWindows

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)