user6499401
user6499401

Reputation:

AppHangB1 trying to bring an Outlook.Explorer to the fore

We have an application that may under some circumstances launch Outlook. It gets an Outlook.Explorer object (oWindow As Outlook.Explorer) and calls its .Activate() procedure.

Up to that point all is hunky dory, but then I want to bring the Explorer object to the foreground, and we call this procedure:

Public Shared Sub BringToFore(ByVal oWindow As Object)

    Dim oFoo As IOleWindow
    Dim hWnd As IntPtr

    oFoo = TryCast(oWindow, IOleWindow)
    If Not (oFoo Is Nothing) Then
        Try
            oFoo.GetWindow(hWnd)
        Catch ex As Exception

        End Try
    End If

    Try
        If hWnd.ToInt32 <> IntPtr.Zero.ToInt32 Then
            Try
                If IsIconic(hWnd) Then
                    ShowWindow(hWnd, SW_RESTORE)
                End If
                SetForegroundWindow(hWnd)
            Catch ex As System.Exception

            End Try
        Else

        End If

    Catch ex As Exception

    End Try

End Sub

IOleWindow is defined as follows:

<ComImport(), Guid("00000114-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Private Interface IOleWindow
    ''' <summary>
    ''' Returns the window handle to one of the windows participating in in-place activation
    ''' (frame, document, parent, or in-place object window).
    ''' </summary>
    ''' <param name="phwnd">Pointer to where to return the window handle.</param>
    Sub GetWindow(<System.Runtime.InteropServices.Out()> ByRef phwnd As IntPtr)

    ''' <summary>
    ''' Determines whether context-sensitive help mode should be entered during an
    ''' in-place activation session.
    ''' </summary>
    ''' <param name="fEnterMode"><c>true</c> if help mode should be entered;
    ''' <c>false</c> if it should be exited.</param>
    Sub ContextSensitiveHelp(<[In](), MarshalAs(UnmanagedType.Bool)> ByVal fEnterMode As Boolean)
End Interface

and the usual declarations

Private Const SW_RESTORE As Integer = 9
Private Declare Auto Function IsIconic Lib "user32" (ByVal hWnd As IntPtr) As Boolean
Private Declare Auto Function SetForegroundWindow Lib "user32" (ByVal hwnd As IntPtr) As Long
Private Declare Auto Function ShowWindow Lib "user32" (ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As IntPtr

The BringToFore procedure works fine most of the time. And sometimes the calling application - a WPF application - just hangs. The Event Viewer records an AppHangB1 and the application crashes.

Is there anything I can do in the BringToFore procedure to prevent this happening? Any idea which of these are causing the problem? TryCast(oWindow, IOleWindow), oFoo.GetWindow(hWnd), IsIconic(hWnd), ShowWindow(hWnd, SW_RESTORE) or SetForegroundWindow(hWnd)? (I personally suspect it may be SetForegroundWindow, to be honest). If so, is there anything I can do in the code? Some condition to check? If this condition is true then don't try to do that ..... sort of thing? I'd rather not go as far as just abandoning the idea of setting the Explorer to the foreground; in that circumstance Outlook may appear "behind" my application and some users may just not realise that something has happened.... if you catch my drift.

Thanks

Pino

Upvotes: 0

Views: 592

Answers (2)

Dmitry Streblechenko
Dmitry Streblechenko

Reputation: 66286

Windows would prevent you from using SetForegroundWindow if the window belongs to a process other than the active one. You'd need to call AttachThreadInput first. Here is the function (Delphi):

function ForceForegroundWindow(hWnd: THandle): BOOL;
var
  hCurWnd: THandle;
begin
  hCurWnd := GetForegroundWindow;
  AttachThreadInput(
    GetWindowThreadProcessId(hCurWnd, nil),
    GetCurrentThreadId, True);
  Result := SetForegroundWindow(hWnd);
  AttachThreadInput(
    GetWindowThreadProcessId(hCurWnd, nil),
    GetCurrentThreadId, False);
end;

Upvotes: 1

Joshg345
Joshg345

Reputation: 74

I think this issue would require more debugging. I found a similar issue posted here quite a few years back with a suggestion which might be useful to get to the root cause.

Upvotes: 0

Related Questions