AppHangB1试图让Outlook.Explorer脱颖而出

时间:2018-07-20 14:21:23

标签: vb.net visual-studio outlook

我们有一个在某些情况下可能启动Outlook的应用程序。它获取一个Outlook.Explorer对象(oWindow为Outlook.Explorer),并调用其.Activate()过程。

到那时为止,一切都是笨拙的,但是接下来我想将Explorer对象放到前台,我们称之为以下过程:

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的定义如下:

<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

和通常的声明

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

BringToFore过程在大多数情况下都能正常运行。有时调用应用程序(WPF应用程序)只是挂起。事件查看器记录一个AppHangB1,应用程序崩溃。

在BringToFore过程中可以做些什么来防止这种情况发生吗?知道其中哪些导致了问题吗? TryCast(oWindow,IOleWindow),oFoo.GetWindow(hWnd),IsIconic(hWnd),ShowWindow(hWnd,SW_RESTORE)或SetForegroundWindow(hWnd)吗? (老实说,我个人怀疑它可能是SetForegroundWindow)。如果是这样,我可以在代码中做些什么?有条件检查吗?如果 this 条件为true,那么不要尝试执行那个 .....之类的事情?我只想放弃将资源管理器设置为前台的想法;在这种情况下,Outlook可能会出现在我的应用程序的“后面”,而某些用户可能只是不知道发生了什么事……。

谢谢

皮诺

2 个答案:

答案 0 :(得分:2)

如果窗口属于活动进程以外的其他进程,则Windows将阻止您使用SetForegroundWindow。您需要先致电AttachThreadInput。这是函数(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;

答案 1 :(得分:1)

我认为此问题将需要更多调试。我发现几年前here发布了一个类似的问题,其中提出了一个建议,可能对于找出根本原因很有帮助。