question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Construction of `AccessibleObject` forces creation of `Handle`

See original GitHub issue
  • .NET Core Version: .NET 5 P4

Problem description:

Multiple code paths involving a construction or an interaction with an AccessibleObject on a control that hasn’t had its Handle created cause the creation of the Handle. This may lead to undesired side-effects like described in https://github.com/dotnet/winforms/issues/2797.

Expected behavior:

None of AccessibleObject events must be raised if an owner control doesn’t have a valid `Handle. https://github.com/dotnet/winforms/blob/b666dc7a94d8ac87a7d300cfb4fa86332fb79bae/src/System.Windows.Forms/src/System/Windows/Forms/AccessibleObject.cs#L2227-L2294

Minimal repro:

Run the following test: https://github.com/dotnet/winforms/blob/b666dc7a94d8ac87a7d300cfb4fa86332fb79bae/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripItemTests.cs#L14005-L14022

Line:14014 will cause ToolStripItem.Handle to be created.

 	System.Windows.Forms.dll!System.Windows.Forms.Control.CreateHandle() Line 4912	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.Control.Handle.get() Line 2464	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.Control.ControlAccessibleObject.ControlAccessibleObject(System.Windows.Forms.Control ownerControl = {System.Windows.Forms.ToolStrip}) Line 32	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.ToolStrip.ToolStripAccessibleObject.ToolStripAccessibleObject(System.Windows.Forms.ToolStrip owner = {System.Windows.Forms.ToolStrip}) Line 5016	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.ToolStrip.CreateAccessibilityInstance() Line 4985	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.Control.AccessibilityObject.get() Line 498	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.ToolStripItemAccessibleObject.FragmentRoot.get() Line 364	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.AccessibleObject.Interop.UiaCore.IRawElementProviderFragment.FragmentRoot.get() Line 819	C#	Symbols loaded.
 	[Native to Managed Transition]		Annotated Frame
 	[Managed to Native Transition]		Annotated Frame
 	System.Windows.Forms.dll!System.Windows.Forms.AccessibleObject.RaiseAutomationEvent(Interop.UiaCore.UIA eventId = AutomationFocusChangedEventId) Line 2267	C#	Symbols loaded.
>	System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.ToolStripItemAccessibleObject.RaiseFocusChanged() Line 481	C#	Symbols loaded.
 	System.Windows.Forms.dll!System.Windows.Forms.ToolStripItem.Select() Line 3094	C#	Symbols loaded.
 	System.Windows.Forms.Tests.dll!System.Windows.Forms.Tests.ToolStripItemTests.ToolStripItem_Select_InvokeWithParent_Success() Line 14017	C#	Symbols loaded.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:9 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
RussKiecommented, Apr 15, 2020

We could, for example, add the following guard and then run tests:

diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/Control.ControlAccessibleObject.cs b/src/System.Windows.Forms/src/System/Windows/Forms/Control.ControlAccessibleObject.cs
index b1bb53959..fa1699363 100644
--- a/src/System.Windows.Forms/src/System/Windows/Forms/Control.ControlAccessibleObject.cs
+++ b/src/System.Windows.Forms/src/System/Windows/Forms/Control.ControlAccessibleObject.cs
@@ -29,6 +29,12 @@ namespace System.Windows.Forms
             public ControlAccessibleObject(Control ownerControl)
             {
                 Owner = ownerControl ?? throw new ArgumentNullException(nameof(ownerControl));
+
+                if (!ownerControl.IsHandleCreated)
+                {
+                    Debug.Fail("Accessibility object must not be created for a control without a valid handle");
+                }
+
                 IntPtr handle = ownerControl.Handle;
                 Handle = handle;
             }

This guard will crash the test runner, highlighting the paths where we fire off accessibility events on controls without valid handles.

Would this be a correct approach?

0reactions
vladimir-krestovcommented, Jun 11, 2020

We don’t need to change Handle.get because _handle is set when creating control Handle (OnHandleCreated method). And if Handle is created then (Owner.Handle == _handle).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Control Class (System.Windows.Forms)
Forces the re-creation of the handle for the control. RectangleToClient(Rectangle). Computes the size and location of the specified screen rectangle in client ...
Read more >
ScrollBarBase Members | WinForms Controls
CreateControl(), Forces the creation of the visible control, including the creation of the handle and any visible child controls. Inherited from Control.
Read more >
Empirically Adapted Model for the Handling of Variable ...
The resulting gripping force is influenced by different factors, which are described in Fig. 3. The influences are divided into three categories ...
Read more >
mono - Mono Documentation
Either force handle creation by calling the Control.Handle property, or wait until the Form.Load event to start the background process.
Read more >
All Classes and Interfaces (Java SE 20 & JDK 20)
The AccessibleObject class is the base class for Field , Method , and Constructor objects (known as reflected objects). AccessibleRelation. Class ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found