- 
                Notifications
    
You must be signed in to change notification settings  - Fork 1.1k
 
Description
- .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 #2797.
Expected behavior:
None of AccessibleObject events must be raised if an owner control doesn't have a valid `Handle.
winforms/src/System.Windows.Forms/src/System/Windows/Forms/AccessibleObject.cs
Lines 2227 to 2294 in b666dc7
| public bool RaiseAutomationNotification(AutomationNotificationKind notificationKind, AutomationNotificationProcessing notificationProcessing, string notificationText) | |
| { | |
| if (!notificationEventAvailable) | |
| { | |
| return false; | |
| } | |
| try | |
| { | |
| // The activityId can be any string. It cannot be null. It is not used currently. | |
| HRESULT result = UiaCore.UiaRaiseNotificationEvent( | |
| this, | |
| notificationKind, | |
| notificationProcessing, | |
| notificationText, | |
| string.Empty); | |
| return result == HRESULT.S_OK; | |
| } | |
| catch (EntryPointNotFoundException) | |
| { | |
| // The UIA Notification event is not available, so don't attempt to raise it again. | |
| notificationEventAvailable = false; | |
| return false; | |
| } | |
| } | |
| /// <summary> | |
| /// Raises the LiveRegionChanged UIA event. | |
| /// This method must be overridden in derived classes that support the UIA live region feature. | |
| /// </summary> | |
| /// <returns>True if operation succeeds, False otherwise.</returns> | |
| public virtual bool RaiseLiveRegionChanged() | |
| { | |
| throw new NotSupportedException(SR.AccessibleObjectLiveRegionNotSupported); | |
| } | |
| internal bool RaiseAutomationEvent(UiaCore.UIA eventId) | |
| { | |
| if (UiaCore.UiaClientsAreListening().IsTrue()) | |
| { | |
| HRESULT result = UiaCore.UiaRaiseAutomationEvent(this, eventId); | |
| return result == HRESULT.S_OK; | |
| } | |
| return false; | |
| } | |
| internal bool RaiseAutomationPropertyChangedEvent(UiaCore.UIA propertyId, object oldValue, object newValue) | |
| { | |
| if (UiaCore.UiaClientsAreListening().IsTrue()) | |
| { | |
| HRESULT result = UiaCore.UiaRaiseAutomationPropertyChangedEvent(this, propertyId, oldValue, newValue); | |
| return result == HRESULT.S_OK; | |
| } | |
| return false; | |
| } | |
| internal bool RaiseStructureChangedEvent(UiaCore.StructureChangeType structureChangeType, int[] runtimeId) | |
| { | |
| if (UiaCore.UiaClientsAreListening().IsTrue()) | |
| { | |
| HRESULT result = UiaCore.UiaRaiseStructureChangedEvent(this, structureChangeType, runtimeId, runtimeId == null ? 0 : runtimeId.Length); | |
| return result == HRESULT.S_OK; | |
| } | |
| return false; | |
| } | 
Minimal repro:
Run the following test:
winforms/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ToolStripItemTests.cs
Lines 14005 to 14022 in b666dc7
| [WinFormsFact] | |
| public void ToolStripItem_Select_InvokeWithParent_Success() | |
| { | |
| using var parent = new ToolStrip(); | |
| using var item = new SubToolStripItem | |
| { | |
| Parent = parent | |
| }; | |
| item.Select(); | |
| Assert.True(item.Selected); | |
| Assert.False(parent.IsHandleCreated); | |
| // Select again. | |
| item.Select(); | |
| Assert.True(item.Selected); | |
| Assert.False(parent.IsHandleCreated); | |
| } | 
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.