So, I’m working on my WPF application and everything runs fine, but when I close it, I get this error message (together with this doesn’t-say-me-anything stacktrace):
[System.ComponentModel.Win32Exception] {"Invalid window handle"}
WindowsBase.dll!MS.Win32.HwndWrapper.DestroyWindow(object args) + 0x11a bytes
WindowsBase.dll!MS.Win32.HwndWrapper.Dispose(bool disposing, bool isHwndBeingDestroyed) + 0x8c bytes
WindowsBase.dll!MS.Win32.HwndWrapper.Dispose() + 0x14 bytes
PresentationCore.dll!System.Windows.Interop.HwndSource.Dispose(bool disposing) + 0x1f6 bytes
PresentationCore.dll!System.Windows.Interop.HwndSource.WeakEventDispatcherShutdown.OnShutdownFinished(object sender, System.EventArgs e) + 0x33 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.ShutdownImplInSecurityContext(object state) + 0x49 bytes
mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x51 bytes
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6a bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0x7e bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.ShutdownImpl() + 0x72 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0xe1 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x17 bytes
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes
PresentationFramework.dll!System.Windows.Application.Run() + 0x1b bytes
GuideDock.exe!GuideDock.App.Main() + 0x94 bytes
mscoreei.dll!__CorExeMain@0() + 0x38 bytes
mscoree.dll!748c7f16()
[Frames below may be incorrect and/or missing, no symbols loaded for mscoree.dll]
mscoree.dll!748c4de3()
kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
This problem seemed to appear only randomly until I figured it out today. The problem can be reproduce by this XAML/C# code (together with a WPF window):
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
this.m_touchCanvas.MouseLeave += (s, e) => CrashAppOnClose();
}
private void CrashAppOnClose() {
Window wnd = Window.GetWindow(this.m_touchCanvas);
// This line throws a Win32Exception with "Ivalid window handle".
wnd.PointToScreen(new Point());
}
}
|
Now, when the user closes the window (without using the mouse; eg. with Alt+F4) while the mouse is still in the window, the call to wnd.PointToScreen()
(line 11) results in the Win32Exception
above. Unfortunately, the doesn’t seem to be any way to check whether this exception will be thrown – I already tried Window.IsLoaded
as suggested here with no luck.
What’s more annoying is that the call to PointToScreen()
does not appear in the stacktrace. I can’t even imaging how this is possible. That’s why it took me ages to figure this one out.
Btw: I’d like to send a bug report to Microsoft but they haven’t got my account working in three months.
Download the example project
Updates:
Solution/Workaround:
Given the 32-bit error message – which reads “This Visual is not connected to a PresentationSource.” – I found a way to circumvent this problem. You need to use PresentationSource.FromVisual like this:
private void CrashAppOnClose() {
Window wnd = Window.GetWindow(this.m_touchCanvas);
if (PresentationSource.FromVisual(wnd) != null) {
wnd.PointToScreen(new Point());
}
}