Skip to content

[System.Management] Make generated WMI wrappers disposable - #132432

Merged
jeffhandley merged 6 commits into
dotnet:mainfrom
Macromullet:issue-127678-disposable-wmi-wrappers
Aug 18, 2026
Merged

jeffhandley merged 6 commits into
dotnet:mainfrom
Macromullet:issue-127678-disposable-wmi-wrappers

Conversation

@Macromullet

Copy link
Copy Markdown
Contributor

Fixes #127678

Summary

  • Make generated strongly typed WMI collection wrappers implement IDisposable and dispose their underlying ManagementObjectCollection.
  • Make generated enumerator wrappers implement IDisposable and dispose their underlying ManagementObjectEnumerator.
  • Add regression coverage that verifies both generated CodeDOM types preserve the disposable ownership contract.

This is additive to generated source and exposes the lifetime contract already implemented by the wrapped System.Management types. Existing finalizer fallback remains unchanged, while consumers can now release COM-backed WMI resources deterministically.

Testing

  • build.cmd clr+libs -rc Release (0 warnings, 0 errors)
  • Full System.Management.Tests project via dotnet build /t:test
    • .NET 11: 27 total, 0 failed, 4 environment-dependent skips
    • .NET Framework: 25 total, 0 failed, 4 environment-dependent skips
  • Generated and compiled a C# Win32_LogicalDisk wrapper, enumerated it, disposed both generated wrappers, and verified both wrapped System.Management objects were disposed.
  • Generated and compiled the equivalent Visual Basic wrapper.

Note

This pull request description was generated with GitHub Copilot.

Have strongly typed WMI collection and enumerator wrappers implement IDisposable and forward disposal to their underlying System.Management objects.

Add regression coverage for both generated wrapper types.

Fix dotnet#127678

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3efc1632-89c0-456b-9be0-ab5cbf335145
Copilot AI lite review requested due to automatic review settings August 17, 2026 22:10
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Aug 17, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-management
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the System.Management strongly typed WMI CodeDOM generator to preserve the disposal contract of the underlying WMI collection/enumerator types, and adds regression tests that validate the generated CodeDOM shape.

Changes:

  • Generate nested WMI collection wrappers that implement IDisposable and forward Dispose() to the wrapped ManagementObjectCollection.
  • Generate nested enumerator wrappers that implement IDisposable and forward Dispose() to the wrapped ManagementObjectEnumerator.
  • Add a regression test that validates both generated wrapper types implement IDisposable and contain a Dispose() implementation that disposes the wrapped field.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/libraries/System.Management/tests/System/Management/ManagementClassTests.cs Adds regression coverage asserting the generated collection/enumerator CodeDOM types implement IDisposable and dispose their wrapped fields.
src/libraries/System.Management/src/System/Management/WMIGenerator.cs Updates the WMI wrapper generator to emit IDisposable on generated collection/enumerator wrappers and emit a forwarding Dispose() method.
Suppressed comments (1)

src/libraries/System.Management/src/System/Management/WMIGenerator.cs:4476

  • The pseudo-code comment for the generated Dispose method uses ObjectEnumerator, but the generated field/method body uses privObjEnum. This comment is now misleading after the change and should match the emitted member names.
            //public void Dispose()
            //{
            //    ObjectEnumerator.Dispose();
            //}

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 17, 2026 22:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.Management/src/System/Management/WMIGenerator.cs:4446

  • The comment describing the generated enumerator wrapper’s implemented interfaces is now stale after adding IDisposable. Updating it helps keep the generator’s intent clear and avoids future confusion.
            //public class ServiceEnumerator : IEnumerator
            ecc = new CodeTypeDeclaration(PrivateNamesUsed["EnumeratorClass"].ToString());
            ecc.TypeAttributes = TypeAttributes.NestedPublic;

            ecc.BaseTypes.Add("System.Object");
            ecc.BaseTypes.Add("System.Collections.IEnumerator");
            ecc.BaseTypes.Add("System.IDisposable");

src/libraries/System.Management/src/System/Management/WMIGenerator.cs:4249

  • The comment describing the generated collection wrapper’s implemented interfaces is now stale after adding IDisposable. This can mislead future edits of the generator; please update it to match the generated BaseTypes.

This issue also appears on line 4440 of the same file.

            //public class ServiceCollection : ICollection, IEnumerable
            ccc = new CodeTypeDeclaration(PrivateNamesUsed["CollectionClass"].ToString());

            ccc.BaseTypes.Add("System.Object");
            ccc.BaseTypes.Add("ICollection");
            ccc.BaseTypes.Add("System.IDisposable");

Keep the pseudo-code comments aligned with the IDisposable interfaces and wrapped field names emitted by the generator.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3efc1632-89c0-456b-9be0-ab5cbf335145
Preserve the suggestion applied through GitHub while retaining the remaining generated-code comment corrections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 3efc1632-89c0-456b-9be0-ab5cbf335145
Copilot AI review requested due to automatic review settings August 17, 2026 22:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@jeffhandley jeffhandley left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to wait for CI to finish before committing this suggestion. But afterward applying this suggestion, this looks good to me. Thanks, @Macromullet!

Comment thread src/libraries/System.Management/tests/System/Management/ManagementClassTests.cs Outdated
@jeffhandley

Copy link
Copy Markdown
Member

…mentClassTests.cs

Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
Copilot AI review requested due to automatic review settings August 18, 2026 19:37
@jeffhandley
jeffhandley merged commit a0f44df into dotnet:main Aug 18, 2026
16 of 23 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/libraries/System.Management/src/System/Management/WMIGenerator.cs:4481

  • Same issue as the collection Dispose: MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Override is not a valid scope combination and can cause the CodeDOM C# generator to emit virtual unexpectedly. Use a single scope value (e.g., Final) for a non-virtual Dispose implementation.
            cmm = new CodeMemberMethod();
            cmm.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Override;
            cmm.Name = "Dispose";
            cmm.ImplementationTypes.Add("System.IDisposable");

src/libraries/System.Management/src/System/Management/WMIGenerator.cs:4282

  • MemberAttributes values under ScopeMask are mutually exclusive (not flags). Public | Final | Override produces an undefined scope value, and the C# CodeDOM generator falls back to emitting virtual (see CSharpCodeGenerator.OutputMemberScopeModifier). For Dispose, that means generated wrappers will have a virtual Dispose method unintentionally. Drop Override (and keep Final if desired) so the emitted code is non-virtual.

This issue also appears on line 4478 of the same file.

            cmm = new CodeMemberMethod();
            cmm.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Override;
            cmm.Name = "Dispose";
            cmm.ImplementationTypes.Add("System.IDisposable");

@build-analysis build-analysis Bot mentioned this pull request Aug 18, 2026
3 tasks
@jeffhandley

Copy link
Copy Markdown
Member

/backport to release/11.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0 (link to workflow run)

@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Aug 21, 2026
jeffhandley added a commit that referenced this pull request Aug 29, 2026
…able (#132587)

Backport of #132432 to release/11.0

## Customer Impact

- [x] Customer reported
- [ ] Found internally

Customer reported, customer fixed, and customer validated.

Fixes #127678. Generated WMI collection and enumerator wrappers now
implement `IDisposable`, allowing consumers to deterministically release
underlying COM-backed WMI resources.

## Regression

- [ ] Yes
- [x] No

## Testing

- New test coverage added for disposal scenarios, and existing coverage
stayed intact.

## Risk

Low. This is an additive implementation of `IDisposable` that exposes
the disposal behavior already supported by the wrapped types. Existing
finalizer fallback remains unchanged.

If a consumer was relying on proper disposal not occurring, they would
not observe the difference. Making that change in .NET 11 vs. aiming for
a servicing release reduces the risk of that change being unacceptable.

> [!NOTE]
> This pull request description was generated with GitHub Copilot.

Co-authored-by: Brooke Philpott <brphilpott@yahoo.com>
Co-authored-by: Brooke Philpott <5089620+Macromullet@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
Copilot-Session: 3efc1632-89c0-456b-9be0-ab5cbf335145
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Management community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

System.Management strongly typed WMI generator emits non-disposable wrappers over disposable WMI resources

3 participants