How do I Task Switch to another process in VBA if all I have is a Process Id?

I am writting a subroutine that needs to switch to a window thats running in another process.  I tried using "AppActivate" to switch windows but my program breaks when a user opens a document or a child window in the target process.  I tried using the "FindWindow" and "SetForgroundWindow" functions from user32 but they had similar problem.  Does anyone know of a way around this problem?
Who is Participating?
zzzzzoocConnect With a Mentor Commented:
Feeling lazy and this question seems to be asked a lot so I searched for a prior answer.. the below should do the trick:

It'll basically just loop through all of the window handles, get their Process ID via GetWindowThreadProcessId and compare it to the shelled processes' Process ID. When it finds a match, currwnd is the window you're after.It's not masterfully done but the example provides the basics.
Are you trying to set focus to a child window in a parent window (such as the edit box in notepad) or are you just trying to set focus to a parent window (such as notepad itself)? Also.. what do you mean by "breaks"?
For the sake of doing so.. here's an example (further down atleast).

The main problem with using ShowWindow/SetForegroundWindow/etc is the possibility of the window being a child of or related to another window. Tests with notepad and calc both yielded "hangs" (100% cpu usage) which you may be referring to with "break".

The below example shells notepad (minimized without focus.. shelled so I have a ProcID to work with) and uses ShowWindow & SetForegroundWindow on the owner of the window associated with the Process ID. Works fine for me.


Private Declare Function GetWindow Lib "User32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "User32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
Private Declare Function ShowWindow Lib "User32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function SetForegroundWindow Lib "User32" (ByVal hWnd As Long) As Long

Private Const GW_HWNDFIRST = 0
Private Const GW_HWNDNEXT = 2
Private Const GW_OWNER = 4

Private Const SW_SHOWNORMAL = 1
Private Sub Form_Load()
    Dim lHandle As Long, lProcIDFind As Long, lProcID As Long
    Dim lTimer As Long
    Call Me.Show
    'Open testing app..
    lProcIDFind = Shell("notepad.exe", vbMinimizedNoFocus)
    'Wait for it to open..
    Call Pause(3)
    lHandle = GetWindow(Me.hWnd, GW_HWNDFIRST)
    Do Until lHandle = 0
        Call GetWindowThreadProcessId(lHandle, lProcID)
        If lProcID = lProcIDFind Then
            'Found a match
            lHandle = GetWindow(lHandle, GW_OWNER)
            Call ShowWindow(lHandle, SW_SHOWNORMAL)
            Call SetForegroundWindow(lHandle)
            Exit Sub
        End If
        lHandle = GetWindow(lHandle, GW_HWNDNEXT)
End Sub
Private Sub Pause(ByVal iSecs As Integer)
    Dim lTimer As Long
    lTimer = Timer + iSecs
    Do Until Timer > lTimer
End Sub

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

As I read, when you try to use ShowWindow/SetForegroundWindow API's, your app hangs with 100% CPU usage ? If this is the problem, try this API:

Description from win32.hlp (

The SendNotifyMessage function sends the specified message to a window. If the window was created by the calling thread, SendNotifyMessage calls the window procedure for the window and does not return until the window procedure has processed the message. If the window was created by a different thread, SendNotifyMessage passes the message to the window procedure and returns immediately; it does not wait for the window procedure to finish processing the message.

As a message, place WM_ACTIVATE or WM_APPACTIVATE.
Also you can try with SetActiveWindow API.
>> As I read, when you try to use ShowWindow/SetForegroundWindow API's, your app hangs with 100% CPU usage ?

It's probably just an issue with trying to SetForegroundWindow/ShowWindow->Maximized a child window who's parent is minimized. Seems like a logical issue also. :P
Alford-MillerAuthor Commented:
Hello zzzzzooc, I need to reuse this code in a number of VB/VBA application at my site where sometime the process will be in a shell script or executable.  Is there any way to gather the window handle from a Proccess Id.  That would be esier because I can get the process Id from WMI.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.