将特定程序 'path\app.exe' 带到前台,如果它是 运行 使用 vb6 中的 api

Bring, to foreground, a specific program 'path\app.exe' if it is running using api in vb6

我正在尝试使用 vb6 中的 api 函数,如果它是 运行,它将允许我将程序带到前台。在这一点上,我将使用 sendkeys 将击键发送到有问题的程序。

奇怪的是,我对该程序的唯一了解是它的路径和 .exe 名称。例如,'c:\anyfolder\anyprog.exe'.

如果我了解有关该程序的其他信息,我可以找到有关如何执行此操作的各种信息,但如果我只知道以上内容(甚至不知道标题栏在前台时显示的内容,程序本身会定期更改)。

有办法吗?

到目前为止,在 Remy 的帮助下,我得到了这个 vb6 代码,我尝试将 C 代码从 Taking a Snapshot and Viewing Processes 转换为 vb6。但这不是很有效,有什么想法吗?

Private Sub FillLists_Click()
   PathList.Clear
   FileNameList.Clear
   Dim p As Long
   Dim m As Long
   Dim ml As Long
   Dim hProcessSnapshot As Long
   Dim h As Long
   Dim hl As Long
   Dim uProcess As PROCESSENTRY32
   Dim uModule As MODULEENTRY32

   hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0&)
   If hProcessSnapshot = 0 Then Exit Sub

   uProcess.dwSize = Len(uProcess)
   p = ProcessFirst(hProcessSnapshot, uProcess)
   Do While p 'as long as p is not 0
      h = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, uProcess.th32ProcessID)
      hl = GetLastError()

      uModule.dwSize = Len(uModule)
      m = Module32First(h, uModule)
      ml = GetLastError()

      PathList.AddItem "h=" & h & " hl=" & hl & " m=" & m & " ml=" & ml & uModule.szModule

      FileNameList.AddItem uProcess.szExeFile

      Call CloseHandle(h)
      p = ProcessNext(hProcessSnapshot, uProcess)
   Loop
   Call CloseHandle(hProcessSnapshot)
End Sub

以及输出结果:

所以,以上没有成功,可能是因为vb6是32位的,而我的电脑是Win7 64位。我在俄罗斯论坛帖子 Google 搜索 'vb6 QueryFullProcessImageName' 时发现了这个函数,无法阅读评论,但代码是金色的!

Function GetProcessNameByPID(pid As Long) As String
    Const PROCESS_QUERY_LIMITED_INFORMATION As Long = &H1000
    Const PROCESS_QUERY_INFORMATION         As Long = &H400
    Const MAX_PATH                          As Long = 260
    Dim hProc               As Long
    Dim Path                As String
    Dim lStr                As Long
    Dim inf(68)             As Long
    Dim IsVistaAndLater     As Boolean
    inf(0) = 276: GetVersionEx inf(0): IsVistaAndLater = inf(1) >= 6
    If Not IsVistaAndLater Then Exit Function
    hProc = OpenProcess(IIf(IsVistaAndLater, PROCESS_QUERY_LIMITED_INFORMATION, PROCESS_QUERY_INFORMATION), False, pid)
    If hProc <> 0 Then 'INVALID_HANDLE_VALUE Then
        lStr = MAX_PATH
        Path = Space(lStr)
        ' minimum Windows Vista !!!!!!!
        If QueryFullProcessImageName(hProc, 0, StrPtr(Path), lStr) Then
            GetProcessNameByPID = Left$(Path, lStr)
        End If
        CloseHandle hProc
    End If
End Function

现在我的代码是:

Private Sub FillLists_Click()
   PathList.Clear
   FileNameList.Clear
   Dim p As Long
   Dim hProcessSnapshot As Long
   Dim uProcess As PROCESSENTRY32

   hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0&)
   If hProcessSnapshot = 0 Then Exit Sub

   uProcess.dwSize = Len(uProcess)
   p = ProcessFirst(hProcessSnapshot, uProcess)
   Do While p 'as long as p is not 0

      PathList.AddItem GetProcessNameByPID(uProcess.th32ProcessID)

      FileNameList.AddItem uProcess.szExeFile

      p = ProcessNext(hProcessSnapshot, uProcess)
   Loop
   Call CloseHandle(hProcessSnapshot)
End Sub

并且输出是(剩下的就是当你找到你想要的那个时做一个 AppActivate uProcess.th32ProcessID):

谢谢雷米!

编辑:小心,事实证明,如果导致另一个应用程序进入前台的应用程序处于最小化状态,则您无法将另一个应用程序带到前台。我还需要仅枚举 Alt-Tab 程序组中的应用程序,并以强制 window 到前台而不是 AppActivate 或 SetForeGroundWindow() 的方式使用 api本身。

你必须:

  1. 枚举所有 运行ning 进程,查看它们的完整路径和文件名,直到找到您感兴趣的进程。使用 EnumProcesses() or CreateToolhelp32Snapshot() for that. See Enumerating All Processes and Taking a Snapshot and Viewing Processes 作为示例。一旦找到所需的文件名,您就会知道它的进程 ID。

  2. 使用EnumWindows() and GetWindowThreadProcessId() to enumerate all top-level windows looking for the one(s) that belong to the same Process ID. Then you can restore those window(s) as needed (if you have permission to do so, that is - see all of the restrictions mentioned in the documentation for SetForegroundWindow()). If a window is minimized, you can try sending it a WM_SYCOMMAND/SC_RESTORE消息。但是,如果 window 已经非最小化但只是没有聚焦,您可能 运行 抵制尝试以编程方式聚焦它。