Skip to content

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

Closed

Description

@Macromullet

Description

ManagementClass.GetStronglyTypedClassCode(...) generates strongly typed WMI wrapper classes via WMIGenerator.cs.

The generated nested collection class wraps ManagementObjectCollection, and the generated nested enumerator wraps ManagementObjectCollection.ManagementObjectEnumerator.

However, the generated collection implements only ICollection, and the generated enumerator implements only IEnumerator. Neither generated type implements IDisposable, even though both wrapped runtime types are disposable and release COM/WMI resources.

Current source

Current generator:

  • src/libraries/System.Management/src/System/Management/WMIGenerator.cs
    • GenerateCollectionClass() emits a collection with:
      • BaseTypes.Add("System.Object")
      • BaseTypes.Add("ICollection")
      • field: ManagementObjectCollection privColObj
    • GenerateEnumeratorClass() emits an enumerator with:
      • BaseTypes.Add("System.Object")
      • BaseTypes.Add("System.Collections.IEnumerator")
      • field: ManagementObjectCollection.ManagementObjectEnumerator privObjEnum

Wrapped runtime types:

  • src/libraries/System.Management/src/System/Management/ManagementObjectCollection.cs
    • ManagementObjectCollection : ICollection, IEnumerable, IDisposable
    • ManagementObjectCollection.ManagementObjectEnumerator : IEnumerator, IDisposable
    • enumerator Dispose() calls Marshal.ReleaseComObject(enumWbem)

Problem

The generated wrapper erases the disposable ownership contract.

Typical generated-code usage looks like normal managed collection enumeration, but under the covers it is wrapping WMI COM enumerators. Because the generated collection/enumerator do not implement IDisposable, consumer code has no obvious deterministic way to release the underlying ManagementObjectCollection / ManagementObjectEnumerator.

In long-running WMI monitoring or inventory services, this can delay COM release until GC/finalization and may contribute to:

  • finalizer queue growth
  • delayed IEnumWbemClassObject release
  • WMI provider pressure
  • WmiPrvSE.exe memory/resource growth
  • RPC/DCOM resource exhaustion
  • intermittent WMI query failures/timeouts
  • retry storms that amplify resource pressure

This is a resource-lifetime correctness issue, not a feature request.

Expected behavior

Generated strongly typed WMI wrappers should preserve the disposable ownership contract of the wrapped System.Management types.

Possible fix:

  1. Generated collection should implement IDisposable and dispose privColObj.
  2. Generated enumerator should implement IDisposable and dispose privObjEnum.
  3. Tests should verify generated CodeTypeDeclaration includes IDisposable for collection/enumerator and emits disposal of the wrapped fields.

Compatibility note

This is additive in generated source. It may affect consumers that diff exact generated output, but it exposes an ownership contract that already exists on the underlying runtime types and enables deterministic cleanup of COM-backed WMI resources.

Activity

  1. dotnet-policy-service commented on May 2, 2026

    @dotnet-policy-service
    Contributor

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

  2. Macromullet commented on May 2, 2026

    @Macromullet
    ContributorAuthor

    I found this years ago and ended up some hacks to fix it, but I don't know why I didn't file a bug. I think at the time .net wasn't on github. It has always bothered me though. I found it two years after we had customers getting RPC port exhaustion, but only by tracking a memory leak. Upon inspection the finalizer queue was huge, because we had a lot of threads using these iterators. It was only then that I had the AHA! moment, realizing that DCOM == RPC. I use gh copilot cli to generate the issue text.

  3. Macromullet commented on May 2, 2026

    @Macromullet
    ContributorAuthor

    @stephentoub I'm happy to make a PR if need be. I don't know how many people that this affects but it can cause RPC port exhaustion so it's not great.

  4. dotnet-policy-service commented on May 2, 2026

    @dotnet-policy-service
    Contributor

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

  5. added
    help wanted[up-for-grabs] Good issue for external contributors
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Aug 17, 2026
  6. added this to the Future milestone on Aug 17, 2026
  7. jeffhandley commented on Aug 17, 2026

    @jeffhandley
    Member

    Thanks for the detailed writeup, @Macromullet — the RPC port exhaustion / finalizer queue detail is exactly the kind of context that makes a report actionable, and sorry for the slow reply.

    Yes please, a PR would be very welcome. I've marked this help wanted and put it on Future, but that reflects our own capacity in this area rather than the value of the fix — if you send a change we'll get it reviewed.

  8. added a commit that references this issue on Aug 18, 2026
    a0f44df
  9. added a commit that references this issue on Aug 29, 2026
    c31f17b
  10. locked and limited conversation to collaborators on Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions