将特定程序 '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本身。
你必须:
枚举所有 运行ning 进程,查看它们的完整路径和文件名,直到找到您感兴趣的进程。使用 EnumProcesses()
or CreateToolhelp32Snapshot()
for that. See Enumerating All Processes and Taking a Snapshot and Viewing Processes 作为示例。一旦找到所需的文件名,您就会知道它的进程 ID。
使用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 已经非最小化但只是没有聚焦,您可能 运行 抵制尝试以编程方式聚焦它。
我正在尝试使用 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本身。
你必须:
枚举所有 运行ning 进程,查看它们的完整路径和文件名,直到找到您感兴趣的进程。使用
EnumProcesses()
orCreateToolhelp32Snapshot()
for that. See Enumerating All Processes and Taking a Snapshot and Viewing Processes 作为示例。一旦找到所需的文件名,您就会知道它的进程 ID。使用
EnumWindows()
andGetWindowThreadProcessId()
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 forSetForegroundWindow()
). If a window is minimized, you can try sending it aWM_SYCOMMAND
/SC_RESTORE
消息。但是,如果 window 已经非最小化但只是没有聚焦,您可能 运行 抵制尝试以编程方式聚焦它。