C# 托管窗口时发生BuildWindowCore错误

C# 托管窗口时发生BuildWindowCore错误,c#,wpf,C#,Wpf,我正在尝试在进程中主持另一个进程的窗口。 为此,我使用了如下HwndHost: public class MyHandle : HwndHost { #region User32.dll private static Int32 WS_VISIBLE = 0x10000000; private static Int32 WS_CHILD = 0x40000000; private static Int32 WS_BORDER = 0x00800000;

我正在尝试在进程中主持另一个进程的窗口。 为此,我使用了如下
HwndHost

public class MyHandle : HwndHost
{
    #region User32.dll

    private static Int32 WS_VISIBLE = 0x10000000;
    private static Int32 WS_CHILD = 0x40000000;
    private static Int32 WS_BORDER = 0x00800000;
    private static Int32 GWL_STYLE = -16;

    [DllImport("user32.dll")]
    private static extern int GetWindowThreadProcessId(IntPtr hWnd, IntPtr procid);

    [DllImport("user32.dll")]
    private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32")]
    private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
    #endregion
    private Action WindowCoreBuilt = null;

    private IntPtr m_window = IntPtr.Zero;

    public MyHandle(IntPtr window, Action windowCoreBuiltDelegate)
    {
        m_window = window;
        WindowCoreBuilt = windowCoreBuiltDelegate;
    }

    protected override System.Runtime.InteropServices.HandleRef BuildWindowCore(System.Runtime.InteropServices.HandleRef hwndParent)
    {
        int guestStyle = SetWindowLong(m_window, GWL_STYLE, WS_CHILD | WS_BORDER | WS_VISIBLE);
        SetParent(m_window, hwndParent.Handle);

        HandleRef hwnd = new HandleRef(this, m_window);
        InvokeHelper.InvokeDelegate(this.Dispatcher, () => WindowCoreBuilt());
        return hwnd;
    }

    protected override void DestroyWindowCore(HandleRef hwnd)
    {
    }
}
它通常是有效的,但有时我会遇到这样的例外:

System.InvalidOperationException: BuildWindowCore failed to return the hosted child window handle.
   at System.Windows.Interop.HwndHost.BuildWindow(HandleRef hwndParent)
   at System.Windows.Interop.HwndHost.BuildOrReparentWindow()
   at System.Windows.Interop.HwndHost.OnSourceChanged(Object sender, SourceChangedEventArgs e)
   at System.Windows.SourceChangedEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
   at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
   at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
   at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
   at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
   at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
   at System.Windows.PresentationSource.UpdateSourceOfElement(DependencyObject doTarget, DependencyObject doAncestor, DependencyObject doOldParent)
   at System.Windows.PresentationSource.OnVisualAncestorChanged(DependencyObject uie, AncestorChangedEventArgs e)
   at System.Windows.UIElement.OnVisualAncestorChanged(Object sender, AncestorChangedEventArgs e)
stacktrace要深入得多,但我认为这与此无关。
我的问题是:
1.是什么原因导致此问题?我如何解决此问题?
2.如何捕获此异常以防止应用程序崩溃?(它发生在我无法访问的系统线程中…)

这是引发异常的特定部分
IsWindow
是函数的直接调用

private void ClearChildControl()
{
    if (null == PlayerPanel)
        return;

    /* this border panel hosts the control of another process */
    PlayerPanel.Child = null;
}

我的猜测是,您正在以某种方式从
BuildWindowCore

返回
IntPtr.Zero
句柄。一旦子控件进程崩溃,您需要将主机控件内容清除为null。如果您不这样做,并且您导航离开主机窗口,然后返回主机窗口,或者导致应用程序以任何方式重新绘制,则此BuildWindowCore()方法将启动并失败

您可以尝试以下技巧,但需要弄清楚控件的宿主进程。拥有Process对象后,可以执行以下操作:

/* on a seperate thread, monitor the process */
Task.Factory.StartNew(() =>
{
    ServiceHostProcess.WaitForExit();
    /* back to the UI thread */
    Application.Current.Dispatcher.Invoke(ClearChildControl);
});
在我的例子中,
ClearChildControl
函数只是将内容清除为null,因此重新绘制尝试甚至不会执行
BuildWindowCore
函数

private void ClearChildControl()
{
    if (null == PlayerPanel)
        return;

    /* this border panel hosts the control of another process */
    PlayerPanel.Child = null;
}
正如“ghord所说,错误来自
HwndHost.BuildWindow
,但是您可以通过确保您提供的HWND不是
IntPtr.Zero
,并且它通过以下方式表示窗口来避免此问题:

[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern bool IsWindow(IntPtr hWnd);

但是,如果提供HWND的进程在您为
BuildWindowCore
的调用提供服务时崩溃,那么除了抛出异常或让基类为您执行异常之外,您别无选择。为避免应用程序崩溃,请处理
应用程序。DispatcherUnandledException
并将
处理的
设置为e> 正确

因为这是主要问题。我没有将所有托管儿童清除为空。你救了我一天,马丁!