Commit 6735caf
authored
Fix InvalidCastException in Control.OnHandleDestroyed for non-ControlAccessibleObject (#14295)
<!-- Please read CONTRIBUTING.md before submitting a pull request -->
Fixes #14291
## Root Cause
`Control.OnHandleDestroyed` used
`Properties.TryGetValue<ControlAccessibleObject>` for both
AccessibilityObject and NcAccessibilityObject, assuming the stored
instance was always a ControlAccessibleObject. When a control overrides
`CreateAccessibleObject()` to return a different AccessibleObject type,
the generic `TryGetValue<T>` attempted an invalid cast and threw
`InvalidCastException` during handle destruction.
## Proposed changes
- Change the lookups in `Control.OnHandleDestroyed` for
`s_accessibilityProperty` and `s_ncAccessibilityProperty` from
`TryGetValue<ControlAccessibleObject>` to
`TryGetValue<AccessibleObject>`, then use type pattern matching (`accObj
is ControlAccessibleObject controlAccObj`) before resetting
`controlAccObj.Handle = IntPtr.Zero`, so only true
`ControlAccessibleObject` instances are manipulated and other
AccessibleObject types no longer cause invalid casts.
<!-- We are in TELL-MODE the following section must be completed -->
## Customer Impact
- This change prevents `InvalidCastException` crashes when controls with
custom accessible objects are destroyed
## Regression?
- Yes (Regress by commit
d08128b#diff-07a0a87cedab0d76c974ce8b105912a1b986c87116c7ee0ac73d6d5d65e4b48aL7643)
## Risk
- Minimal
<!-- end TELL-MODE -->
## Screenshots <!-- Remove this section if PR does not change UI -->
### Before
Sample project:
[WinFormsApp15.zip](https://github.com/user-attachments/files/25253150/WinFormsApp15.zip)
On teardown, If a custom overrode CreateAccessibleObject() and returned
a different AccessibleObject type, TryGetValue<ControlAccessibleObject>
threw an InvalidCastException when the handle was destroyed, potentially
crashing the app.
https://github.com/user-attachments/assets/c37feba7-58f8-47db-a20e-fcc540ebc11d
### After
Custom accessible objects that are not `ControlAccessibleObject` are
left untouched during handle destruction, so no `InvalidCastException`
is thrown and the app stays stable.
https://github.com/user-attachments/assets/9d89b29c-c1b4-4b37-924e-4eaf23bec610
## Test methodology <!-- How did you ensure quality? -->
- Manually
## Test environment(s) <!-- Remove any that don't apply -->
- .net 11.0.0-preview.2.26080.101
<!-- Mention language, UI scaling, or anything else that might be
relevant -->
###### Microsoft Reviewers: [Open in
CodeFlow](https://microsoft.github.io/open-pr/?codeflow=https://github.com/dotnet/winforms/pull/14295)1 parent f75ac9a commit 6735caf
File tree
3 files changed
+20
-3
lines changed- src
- System.Windows.Forms/System/Windows/Forms
- test/unit/System.Windows.Forms/System/Windows/Forms
3 files changed
+20
-3
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7518 | 7518 | | |
7519 | 7519 | | |
7520 | 7520 | | |
7521 | | - | |
| 7521 | + | |
| 7522 | + | |
7522 | 7523 | | |
7523 | | - | |
| 7524 | + | |
7524 | 7525 | | |
7525 | 7526 | | |
7526 | 7527 | | |
7527 | 7528 | | |
7528 | | - | |
| 7529 | + | |
| 7530 | + | |
7529 | 7531 | | |
7530 | 7532 | | |
7531 | 7533 | | |
| |||
Lines changed: 13 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
412 | 412 | | |
413 | 413 | | |
414 | 414 | | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
415 | 428 | | |
416 | 429 | | |
417 | 430 | | |
| |||
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| 103 | + | |
| 104 | + | |
103 | 105 | | |
104 | 106 | | |
105 | 107 | | |
| |||
0 commit comments