Determine if application is running with Excel
You can check this more directly by getting a list of open processes.
This will search based on the process name, returning true/false as appropriate.
Sub exampleIsProcessRunning() Debug.Print IsProcessRunning("MyProgram.EXE") Debug.Print IsProcessRunning("NOT RUNNING.EXE")End SubFunction IsProcessRunning(process As String) Dim objList As Object Set objList = GetObject("winmgmts:") _ .ExecQuery("select * from win32_process where name='" & process & "'") If objList.Count > 0 Then IsProcessRunning = True Else IsProcessRunning = False End IfEnd Function
Here's how I brought the search window to front:
Private Const SW_RESTORE = 9Private Declare Function BringWindowToTop Lib "user32" (ByVal hwnd As Long) As LongPrivate Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As LongPrivate Declare Function ShowWindow Lib "user32" (ByVal hwnd As Long, ByVal nCmdShow As Long) As LongPrivate Sub btnSearch_Click() Dim x As Variant Dim Path As String If IsProcessRunning("MyProgram.exe") = False Then Path = "C:\Tmp\MyProgram.exe" x = Shell(Path, vbNormalFocus) Else Dim THandle As Long THandle = FindWindow(vbEmpty, "Window / Form Text") Dim iret As Long iret = BringWindowToTop(THandle) Call ShowWindow(THandle, SW_RESTORE) End IfEnd Sub
Now if the window was minimized and the user clicks the search button again, the window will simply pop up.
Just want to point out that the Window Text may change when documents are open in the application instance.
For example, I was trying to bring CorelDRAW to focus and everything would work fine so long as there wasn't a document open in Corel, if there was, I would need to pass the complete name to FindWindow()
including the open document.
So, instead of just:
FindWindow("CorelDRAW 2020 (64-Bit)")
It would have to be:
FindWindow("CorelDRAW 2020 (64-Bit) - C:\CompletePath\FileName.cdr")
As that is what would be returned from GetWindowText()
Obviously this is an issue as you don't know what document a user will have open in the application, so for anyone else who may be coming here, years later, who may be experiencing the same issue, here's what I did.
Option ExplicitPrivate ModulePrivate Const EXE_NAME As String = "CorelDRW.exe"Private Const WINDOW_TEXT As String = "CorelDRAW 2020" ' This is common with all opened documentsPrivate Const GW_HWNDNEXT = 2Private Const SW_RESTORE = 9Private Declare PtrSafe Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As LongPrivate Declare PtrSafe Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As LongPrivate Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As Any, ByVal lpWindowName As Any) As LongPrivate Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As LongPublic Sub FocusIfRunning(parAppName as String, parWindowText as String) Dim oProcs As Object Dim lWindowHandle As Long Dim sWindowText As String Dim sBuffer As String ' Create WMI object and execute a WQL query statement to find if your application ' is a running process. The query will return an SWbemObjectSet. Set oProcs = GetObject("winmgmts:").ExecQuery("SELECT * FROM win32_process WHERE " & _ "name = '" & parAppName & "'") ' The Count property of the SWbemObjectSet will be > 0 if there were ' matches to your query. If oProcs.Count > 0 Then ' Go through all the handles checking if the start of the GetWindowText() ' result matches your WindowText pre-file name. ' GetWindowText() needs a buffer, that's what the Space(255) is. lWindowHandle = FindWindow(vbEmpty, vbEmpty) Do While lWindowHandle sBuffer = Space(255) sWindowText = Left(sBuffer, GetWindowText(lWindowHandle, sBuffer, 255)) If Mid(sWindowText, 1, Len(parWindowText)) Like parWindowText Then Exit Do ' Get the next handle. Will return 0 when there are no more. lWindowHandle = GetWindow(lWindowHandle, GW_HWNDNEXT) Loop Call ShowWindow(lWindowHandle , SW_RESTORE) End IfEnd SubPrivate Sub btnFocusWindow_Click() Call FocusIfRunning(EXE_NAME, WINDOW_TEXT)End Sub
Hopefully somebody gets use from this and doesn't have to spend the time on it I did.