2015-12-09 90 views
2

当我试图举办另一个进程的一个窗口,在我的过程。 为此我使用HwndHost这样的:BuildWindowCore错误托管窗口

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) 

堆栈跟踪则深入得多,但我不认为这是相关的。
我的问题是:
1.这是什么原因,我该如何解决?
2.如何捕获此异常以防止我的应用程序崩溃? (它发生在我没有获得一个系统线程...)

回答

1
_hwnd = BuildWindowCore(hwndParent); 

if(_hwnd.Handle == IntPtr.Zero || !UnsafeNativeMethods.IsWindow(_hwnd)) 
{ 
    throw new InvalidOperationException(SR.Get(SRID.ChildWindowNotCreated)); 
} 

这是WPF source code抛出异常特定部分。 IsWindow是直接调用Win32 IsWindow函数。

我的猜测是,你以某种方式从BuildWindowCore返回IntPtr.Zero手柄。

0

你需要清除主机控制的内容尽快子控制进程崩溃空。如果你不这样做,并且你离开主窗口,然后回到主窗口,或者导致应用程序以任何方式重绘,这个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功能,只需清除内容为空,所以重绘尝试甚至不会执行BuildWindowCore功能。

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

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

为“ghord说,这个错误来自HwndHost.BuildWindow,但是你可以通过确保HWND您提供的避免这种不IntPtr.Zero,而且它代表通过一个窗口:

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

但是,如果当你在维修呼叫BuildWindowCore,提供了HWND的进程崩溃,没有什么可以做其他的不是抛出一个异常,或让基类为您代劳。为了避免崩溃,你的应用程序,处理Application.DispatcherUnhandledException并设置Handledtrue