Exception thrown: 'System.ComponentModel.Win32Exception' in WindowsBase.dll (Invalid window handle)
See original GitHub issue(First ever issue report on Github, so bear with me 😃, I am also Dutch, sorry for my English. )
Mentioned in https://github.com/Dirkster99/AvalonDock/issues/270 by @blakepell, I was having the same issues, so I went digging.
The problem is massive amounts of System.ComponentModel.Win32Exception, with the message: “Invalid window handle”. On every input change (like hovering over a button, key input etc). The Problem does look like it only happens inside visual studio (However this does not have to be true, see below)
So I found some more information about this issue and know why it happens and have a workaround, but no fix though, but can be made based on this information.
By Profiling I found out that the error occurs because of Microsoft UI Automation when an automation client is running. (https://docs.microsoft.com/en-us/dotnet/framework/ui-automation/ui-automation-overview)
When you kill all automation clients by this code the exceptions stop (Till you open a new window containing AvalonDock and cause the issues again) (Found it here: https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/6c4465e2-207c-4277-a67f-e0f55eff0110/poor-wpf-application-performance-due-to-ui-automation-on-certain-machines)
public static void RemoveAutomationClients(Dispatcher dispather)
{
Assembly pc = Assembly.GetAssembly(typeof(ContentElement));
Type clmt = pc.GetType("System.Windows.ContextLayoutManager");
MethodInfo mi = clmt.GetMethod("From", BindingFlags.Static | BindingFlags.NonPublic);
object clm = mi.Invoke(null, new object[] { dispather });
PropertyInfo aepi = clm.GetType().GetProperty("AutomationEvents", BindingFlags.Instance | BindingFlags.NonPublic);
object ae = aepi.GetValue(clm, null);
FieldInfo cfi = ae.GetType().GetField("_count", BindingFlags.Instance | BindingFlags.NonPublic);
FieldInfo hfi = ae.GetType().GetField("_head", BindingFlags.Instance | BindingFlags.NonPublic);
MethodInfo rimi = ae.GetType().GetMethod("Remove", BindingFlags.Instance | BindingFlags.NonPublic);
while (((int)cfi.GetValue(ae)) > 0)
{
object listItem = hfi.GetValue(ae);
rimi.Invoke(ae, new object[] { listItem });
}
}
This is why it is always noticed in Visual Studio as it is UI automation client itself (The Live Visual Tree) https://docs.microsoft.com/en-us/visualstudio/xaml-tools/inspect-xaml-properties-while-debugging?view=vs-2019
However disabling it did not prevent the exceptions from happening… but it can be that there is another UI automation client running on my machine (If someone finds a way to check for UI automation clients please let me know).
So the exception starts happening when an empty DockingManager is added to the XAML and you close that window (After playing a little with it, resizing the window etc, it does not always happen) (This is why I am pretty certain it is in AvalonDock, other likely culprit would be MahApps, but because of this unlikely)
Then if I hover over other controls like buttons on the main window (not containing DockingManager) the exceptions start happening.
I noticed when I would not dispose of AvalonDock.Controls.LayoutAutoHideWindowControl (Created by DockManager) the exceptions would not occur, so it seems to be that UI Automation does not dispose of it correctly. (Yes this would be a horrible fix as you should always dispose, this was just testing)
However I quickly found out that this does not fix them all as it almost 100% of the time happens after Undocking a LayoutContent from the DockingManager (making it its own window). After playing a little with it like resize it and close it even more (e.g. 10 each time) the System.ComponentModel.Win32Exception (invalid window handle) exceptions started happening everytime input was given, like hovering over buttons or key input was given.
However they all stop after calling RemoveAutomationClients(…)
I have not read up on how UI automation works fully but that is why I am posting it here, maybe someone more qualified knows this, and maybe I will do later, but I recon the following:
For each non native WPF control (Like LayoutAutoHideWindowControl, that inherits from HwndHost) a custom Automation peer needs to be made so it knows how to handle those controls after it is disposed. Maybe?
EDIT: I started working on a workable workaround that did not involve killing UI Automation every time, till so far no avail. I tried this as it looked promising and a clean solution but it did not work for me: https://stackoverflow.com/a/26433762 Also disabling UI automation by manifest did not work for me.
Also thanks @Dirkster99 for the work on AvalonDock, its amazing 😄 Definitely planning on making a donation if I ever finish my program HaHA!
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:6 (4 by maintainers)
Hi @rmadsen-ks,
Your fix seems to resolve this issue: when adding
at the end of the
BuildWindowCore
method, I don’t get the exceptions anymore!Thank you!
Thanks for verifying it, @perkasthor!