Skip to content

Commit 06f6a6c

Browse files
authored
Fix Control.Dispose crash when dependent UserControl fails to load due to missing assembly (#13840)
<!-- Please read CONTRIBUTING.md before submitting a pull request --> Fixes #13835 ## Root Cause When a control (e.g., MainObject) references another control (ExternalObject) from a separate assembly (ExternalAsm), and that assembly is missing at runtime, the constructor of MainObject fails. However, the .NET runtime still attempts to call `Dispose()` on the partially constructed control. Inside `Control.Dispose`, accessing `ContextMenuStrip` triggers a `NullReferenceException` because `Properties` is not initialized. ## Proposed changes - Added a defensive null check around `ContextMenuStrip` access in `Control.Dispose()` - Replaced direct property access with `Properties?.TryGetValue(...)` to ensure safe event unsubscription <!-- We are in TELL-MODE the following section must be completed --> ## Customer Impact - This change ensures that `Control.Dispose()` can safely execute even when the control was never fully constructed. ## Regression? - Yes ## Risk - Minimal <!-- end TELL-MODE --> ## Screenshots <!-- Remove this section if PR does not change UI --> ### Before Run the attached project [net10Issue.zip](https://github.com/user-attachments/files/22095433/net10Issue.zip) using .NET 10 framework, crash with Exception thrown: 'System.NullReferenceException' in System.Windows.Forms.dll https://github.com/user-attachments/assets/a7b5e494-0e72-48cb-944a-5b9c580f5fd6 ### After App exits successfully. https://github.com/user-attachments/assets/1fe967cd-f68a-4897-b4e3-7990c010957a ## Test methodology <!-- How did you ensure quality? --> - Manually ## Test environment(s) <!-- Remove any that don't apply --> - .net 10.0.0-rc.1.25420.121 <!-- 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/13840)
2 parents f6dbedd + bfdb352 commit 06f6a6c

File tree

1 file changed

+3
-3
lines changed
  • src/System.Windows.Forms/System/Windows/Forms

1 file changed

+3
-3
lines changed

src/System.Windows.Forms/System/Windows/Forms/Control.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4790,7 +4790,7 @@ protected override void Dispose(bool disposing)
47904790
}
47914791

47924792
// Unsubscribes from the Disposed event of the ContextMenuStrip.
4793-
if (ContextMenuStrip is ContextMenuStrip menu)
4793+
if (Properties?.TryGetValue(s_contextMenuStripProperty, out ContextMenuStrip? menu) == true)
47944794
{
47954795
menu.Disposed -= DetachContextMenuStrip;
47964796
}
@@ -4816,10 +4816,10 @@ protected override void Dispose(bool disposing)
48164816
SuspendLayout();
48174817
try
48184818
{
4819-
Properties.RemoveValue(s_ncAccessibilityProperty);
4819+
Properties?.RemoveValue(s_ncAccessibilityProperty);
48204820

48214821
DisposeAxControls();
4822-
Properties.GetValueOrDefault<ActiveXImpl>(s_activeXImplProperty)?.Dispose();
4822+
Properties?.GetValueOrDefault<ActiveXImpl>(s_activeXImplProperty)?.Dispose();
48234823

48244824
ResetBindings();
48254825

0 commit comments

Comments
 (0)