Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MissingMethodException raised from System.Management.WmiNetUtilsHelper during wmi call (.NET6 self-contained) #78038

Closed
wzm199309 opened this issue Nov 8, 2022 · 17 comments
Labels
area-System.Management partner-impact This issue impacts a partner who needs to be kept updated
Milestone

Comments

@wzm199309
Copy link

wzm199309 commented Nov 8, 2022

Description

SQL IaaS team and are now working on project migration to .NET6, here is an issue we identified with System.Management.WmiNetUtilsHelper during testing which seems to be a known issue, want to seek insights to see how we can resolve it:

Issue: Win32_Service WMI call failed with MissingMethodException  exception raised from 'System.Management.WmiNetUtilsHelper'

Reproduction Steps

Code example:

var mgmtScope = new ManagementScope(ReportingHelpers.StorageWmiCimNamespace);
mgmtScope.Connect();
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Volume where DriveType = 3");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(mgmtScope, query))
[Warning] ServerConfigurationsManagementStorageReportErrored: System.Exception: Error occurred when attempting to query SQL Server storage report
---> System.MissingMethodException: Cannot dynamically create an instance of type 'System.Management.WbemDefPath'. Reason: No parameterless constructor defined.
   at System.RuntimeType.ActivatorCache..ctor(RuntimeType )
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean , Boolean )
   at System.Activator.CreateInstance(Type type)
   at System.Management.MTAHelper.CreateInMTA(Type )
   at System.Management.ManagementPath.CreateWbemPath(String )
   at Microsoft.SqlServer.Management.ServerConfigurationsManagement.Common.StorageHelper.GetVolumes()
   at Microsoft.SqlServer.Management.ServerConfigurationsManagement.Queries.SqlQueries.QueryStorageReport(String sqlInstanceName, DrivesStatusMonitor drivesStatusMonitor)
   --- End of inner exception stack trace ---

Expected behavior

WMI call should works

Actual behavior

instead, raising exception

Regression?

No response

Known Workarounds

No response

Configuration

.NET6, windows server 2019, x64

Other information

No response

@carlossanlop carlossanlop added the partner-impact This issue impacts a partner who needs to be kept updated label Nov 8, 2022
@carlossanlop
Copy link
Member

Thanks for reporting. Do you have a small console app where we can repro the issue?

@carlossanlop
Copy link
Member

Reached out to @wzm199309 via Teams (works for the SqlServer team).

The exception message is saying that the type that does not have a default parameterless constructor is this one:

[ClassInterfaceAttribute((short)0x0000)]
[GuidAttribute("CF4CC405-E2C5-4DDD-B3CE-5E7582D8C9FA")]
//[TypeLibTypeAttribute(0x0202)]
[ComImport]
internal class WbemDefPath
{
}

It's been like that since it was added to .NET Core 1.0, and in fact it was brought here unmodified from .NET Framework:
https://referencesource.microsoft.com/#System.Management/InteropClasses/WMIInterop.cs,1945

The exception is thrown here:

RuntimeTypeHandle.GetActivationInfo(rt,
out _pfnAllocator!, out _allocatorFirstArg,
out _pfnCtor!, out _ctorIsPublic);

The type is being passed via typeof here, in CreateWbemPath:

private IWbemPath CreateWbemPath(string path)
{
IWbemPath wbemPath = (IWbemPath)MTAHelper.CreateInMTA(typeof(WbemDefPath)); //new WbemDefPath();

Which means that from the shared callstack, the exception came from the ManagementPath constructor. It's the only place where we call CreateWbemPath:

public ManagementPath(string path)
{
if ((null != path) && (0 < path.Length))
wmiPath = CreateWbemPath(path);

@wzm199309 said that this problem is reproing when adding <BuiltInComInteropSupport>true</BuiltInComInteropSupport> to the project, but does not repro when that is removed.

I found a very similar issue opened last year, where trimming an app would cause this exact same exception to show up (although not exactly from ManagementPath): #49062

@wzm199309 confirmed some of the related projects are trimmed, but not exactly this one throwing the exception. He will disable trimming and try to repro the issue again.

In the meanwhile: @eerhardt @AaronRobinsonMSFT do you know if COM and trimming don't play well together?

@AaronRobinsonMSFT
Copy link
Member

In the meanwhile: @eerhardt @AaronRobinsonMSFT do you know if COM and trimming don't play well together?

They do not. Trimming and COM are incompatible. When an application is trimmed, COM will most likely break because the trimmer is unable to recognize that COM interfaces shouldn't be torn apart. If the trimmer treated interfaces marked as ComImport as roots then support is likely possible, but that isn't the current design. The short story here is trimming breaks COM and if COM is needed trimming is not advised.

/cc @agocke @vitek-karas

@eerhardt
Copy link
Member

eerhardt commented Nov 8, 2022

do you know if COM and trimming don't play well together?

They don't. You need to use COM Wrappers in order to make COM usage "trim compatible".

I don't see the original post saying they are using trimming though.

@agocke
Copy link
Member

agocke commented Nov 8, 2022

@wzm199309 If you are using trimming, you should be getting trim analysis warnings if things are incompatible. Did this show up in that list?

@carlossanlop
Copy link
Member

I don't see the original post saying they are using trimming though.

I asked that information via chat, after I found the related issue #49062. @wzm199309 can give more details on how they are using trimming.

@wzm199309
Copy link
Author

thanks for help, yes we are using trimming at some of our projects (though dont apply it at one which now having the issue)

@vitek-karas
Copy link
Member

though dont apply it at one which now having the issue

This is confusing to me. The default value for BuiltInComInteropSupport is true - meaning if you build an app without trimming the built-in COM is definitely enabled. This changes when you turn on trimming (PublishTrimmed=true) in which case we turn of built-in COM.

So if your project where it fails doesn't specify PublishTrimmed=true then I would expect COM to just work without issues in this case. And also I would expect that setting BuiltInComInteropSupport to true would have no effect.

@wzm199309
Copy link
Author

wzm199309 commented Nov 8, 2022

@vitek-karas Story is this:

  1. At first, I didnt specify BuiltInComInteropSupport=true and we applied trimming in some of our projects
    issue a) WMI call raises error says COM is disabled by default on .NET6
    issue b) WMI call raises TypeLoadException exception at WmiNetUtilsHelper

  2. So I then specify BuiltInComInteropSupport=True and keeps trimming
    issue a and issue b gone, issue c) coming up: WMI call raises MissingMethodException exception at WmiNetUtilsHelper (the one I open this issue for).

  3. now I still keeps specify BuiltInComInteropSupport=True but removing trimming
    Issue c) gone, but package size bumped 50mb up.

@wzm199309
Copy link
Author

@eerhardt eerhardt @agocke got it, so in this case if we want to keep trimming, we need to implement COM Wrappers by our own instead of applying existing COM ? This seems a heavy work.

@eerhardt
Copy link
Member

eerhardt commented Nov 8, 2022

so in this case if we want to keep trimming, we need to implement COM Wrappers by our own instead of applying existing COM ?

An even better approach would be to contribute the COM Wrapper changes to https://github.com/dotnet/runtime/tree/main/src/libraries/System.Management to make that library trim-compatible for everyone.

I believe it is possible to make your app work with BuiltInComInteropSupport=True and keeps trimming by manually preserving IL using DynamicDependencyAttributes or a ILLink.Descriptors.xml file. However, that approach is super fragile and not supported. If you took that approach, you would be responsible for keeping it working and bugs that you hit might not be fixed.

@wzm199309
Copy link
Author

@eerhardt thanks for helping, quick questions: 1) do I need to add all COM wrapper classes to sys.management make it enable trim-compatible? 2) by applying DynamicDependencyAttributes you mean I should apply it for all methods calling WMI like [DynamicDependency(DynamicallyAccessedMemberTypes.All, "System.Mangement", "System.Mangement.dll")]
public void foo(){ wmi calls ....}
any example I can refer to ?

@eerhardt
Copy link
Member

eerhardt commented Nov 9, 2022

  1. do I need to add all COM wrapper classes to sys.management make it enable trim-compatible?

The current list of warnings in System.Management are located here:

<assembly fullname="System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2026</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Management.ManagementClassGenerator.InitializeCodeGenerator(System.Management.CodeLanguage)</property>
</attribute>
<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2057</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Management.ManagementClassGenerator.ProcessNamespaceAndClassName</property>
</attribute>
<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2067</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Management.MTAHelper.CreateInMTA(System.Type)</property>
</attribute>
<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2072</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Management.ManagementClassGenerator.InitializeCodeGenerator(System.Management.CodeLanguage)</property>
</attribute>
<attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
<argument>ILLink</argument>
<argument>IL2077</argument>
<property name="Scope">member</property>
<property name="Target">M:System.Management.MTAHelper.WorkerThread</property>
</attribute>
</assembly>

To make System.Management trim compatible, those warnings would need to be addressed.

  1. by applying DynamicDependencyAttributes you mean I should apply it for all methods calling WMI like [DynamicDependency(DynamicallyAccessedMemberTypes.All, "System.Mangement", "System.Mangement.dll")]
    public void foo(){ wmi calls ....} any example I can refer to ?

Here's an example of trying to do this approach, but it was abandoned and never merged:
0f7ce68

See the discussion at #75176 (comment) for why it was abandoned.

You would apply attributes like that in your application where it is using System.Management.

@carlossanlop carlossanlop added this to the Future milestone Nov 9, 2022
@wzm199309
Copy link
Author

thanks folks for detailed explanations and suggestions. I will try with manual trimming way first then try enabling COM wrapper with trim-abilities.

@cocowalla
Copy link

You need to use COM Wrappers in order to make COM usage "trim compatible"

Do you have any guidance available on how precisely to do that? With wmic.exe going away soon, I need another way to perform WMI queries from an IL-trimmed app.

@eerhardt
Copy link
Member

Do you have any guidance available on how precisely to do that?

https://learn.microsoft.com/en-us/dotnet/standard/native-interop/com-wrappers is the docs on COM Wrappers.

You can see an example of doing this for System.Drawing in these 2 PRs:

@cocowalla
Copy link

@eerhardt wow, that looks like a lot of work just to be able to use ManagementObjectSearcher 😰

I think I'll see what I can get from the Windows Registry (and possibly SMBIOS) instead!

@ghost ghost locked as resolved and limited conversation to collaborators Dec 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Management partner-impact This issue impacts a partner who needs to be kept updated
Projects
None yet
Development

No branches or pull requests

7 participants