如何从 WMI 获取方法

2024-03-21

tl;dr我应该怎么SELECT代替*为了获得方法?

更多信息:

这是一个例子:

using (var s = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM someClass"))
    foreach (var obj in s.Get())

如果我只要求一处房产这还不够 - 我在尝试时遇到异常obj.InvokeMethod(...);.

如果我要求*就足够了但如果可能的话我宁愿避免这种情况。

我没有看到任何用于获取方法的属性(-Disable, Enable,...) 在 WMI 类的文档中。如果是的话not在名单上 - 怎么会*作品?不是应该要求所有吗名单上的人?

EDIT

有人建议使用管理班 https://msdn.microsoft.com/en-us/library/8wzwcace(v=vs.110).aspx代替ManagementObjectSearcher。这是否会加载所有属性,例如*? (如果没有,那是一个很好的答案。虽然在我的实际情况中,除了调用方法的能力之外,我还需要一个属性。我的理论问题仍然是 - 是*不仅仅是all.)


就标题和 TL;DR 所要求的内容而言,无法通过以下方式查询方法SELECT但你可以使用ManagementClass.Methods财产 https://learn.microsoft.com/dotnet/api/system.management.managementclass.methods检查该管理类提供的内容。例如,这段代码...

using (ManagementClass processClass = new ManagementClass("Win32_Process"))
    foreach (MethodData method in processClass.Methods)
    {
        bool isStatic = method.Qualifiers
            .Cast<QualifierData>()
            .Any(qualifier => string.Equals(qualifier.Name, "Static", StringComparison.OrdinalIgnoreCase));

        Console.WriteLine($"{method.Origin}.{method.Name}() [{(isStatic ? "static" : "instance")}]");
        if (method.InParameters != null && method.InParameters.Properties.Count > 0)
        {
            Console.WriteLine("\tInput parameters:");
            foreach (PropertyData parameterProperty in method.InParameters.Properties)
                Console.WriteLine($"\t\t{parameterProperty.Type} {parameterProperty.Name}");
        }
        if (method.OutParameters != null && method.OutParameters.Properties.Count > 0)
        {
            Console.WriteLine("\tOutput parameters:");
            foreach (PropertyData parameterProperty in method.OutParameters.Properties)
                Console.WriteLine($"\t\t{parameterProperty.Type} {parameterProperty.Name}");
        }
    }

...产生这个输出...

Win32_Process.Create() [static]
    Input parameters:
        String CommandLine
        String CurrentDirectory
        Object ProcessStartupInformation
    Output parameters:
        UInt32 ProcessId
        UInt32 ReturnValue
Win32_Process.Terminate() [instance]
    Input parameters:
        UInt32 Reason
    Output parameters:
        UInt32 ReturnValue
Win32_Process.GetOwner() [instance]
    Output parameters:
        String Domain
        UInt32 ReturnValue
        String User
...

除非“获取方法”的含义与我认为的不同(不同于calling方法),问题的其余部分似乎完全在处理其他事情,这是填充的必要性Key调用方法之前的属性。我相信你的另一个问题已经解决了这个问题,为什么 WMI 通过搜索而不是直接工作? https://stackoverflow.com/q/54892478/150605

如果你是什么really询问是“如何确定调用方法所需选择的最小属性集?”,那么您可以通过ManagementClass, 也。该最小属性集是所有具有Key预选赛 https://learn.microsoft.com/windows/win32/wmisdk/key-qualifier,所以你会使用Properties财产 https://learn.microsoft.com/dotnet/api/system.management.managementbaseobject.properties找到任何财产Qualifiers财产 https://learn.microsoft.com/dotnet/api/system.management.propertydata.qualifiers包含一个限定符Name https://learn.microsoft.com/dotnet/api/system.management.qualifierdata.name of "Key".

考虑Win32_Product class https://learn.microsoft.com/previous-versions/windows/desktop/legacy/aa394378(v%3Dvs.85),它代表由 Windows Installer 安装的产品(在我的 Windows 10 系统上确定,与文档不同)these Key特性...

  • IdentifyingNumber
  • Name
  • Version

假设您想要检索要显示的这些属性...

  • PackageName
  • Vendor
  • Version

...然后致电Uninstall() method https://msdn.microsoft.com/library/aa393941对于具有Name of "Microsoft .NET Framework 4.8 SDK"。以下代码显示了尝试此任务的三种不同方法......

  1. Select 所有属性并调用该方法。
  2. Select 仅显示您想要显示的属性并调用该方法。
  3. Select 您要显示的属性加上Key特性并调用该方法。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;

namespace SO49798851
{
    static class Program
    {
        static void Main()
        {
            // Win32_Product is slow to query, so be patient!
            const string className = "Win32_Product";
            const string condition = "Name = 'Microsoft .NET Framework 4.8 SDK'";
            string[] allProperties = new string[] { "*" };
            string[] displayProperties = new string[] { "PackageName", "Vendor", "Version" };
            string[] keyProperties = GetKeyPropertyNames(className);
            string[] displayPlusKeyProperties = displayProperties.Union(keyProperties).ToArray();
            // When run as a non-administrator, the Uninstall() method
            // still returns 0 despite not (appearing to) do anything
            const string methodName = "Uninstall";
            object[] methodArguments = Array.Empty<object>();

            Console.WriteLine($"Key properties for class {className}: {string.Join(", ", keyProperties)}");
            Console.WriteLine();

            FindAndInvoke(className, condition, allProperties,            methodName, methodArguments);
            FindAndInvoke(className, condition, displayProperties,        methodName, methodArguments);
            FindAndInvoke(className, condition, displayPlusKeyProperties, methodName, methodArguments);
        }

        static string[] GetKeyPropertyNames(string className)
        {
            using (ManagementClass managementClass = new ManagementClass(className))
            {
                return managementClass.Properties
                    .Cast<PropertyData>()
                    .Where(
                        property => property.Qualifiers
                            .Cast<QualifierData>()
                            .Any(qualifier => string.Equals(qualifier.Name, "Key", StringComparison.OrdinalIgnoreCase))
                    )
                    .Select(property => property.Name)
                    .ToArray();
            }
        }

        static void FindAndInvoke(
            string className,
            string condition,
            string[] selectedProperties,
            string methodName,
            object[] methodArguments
        )
        {
            if (selectedProperties == null)
                selectedProperties = Array.Empty<string>();

            ObjectQuery query = new SelectQuery(className, condition, selectedProperties);
            bool allPropertiesSelected = selectedProperties.Length < 1
                || selectedProperties.Any(propertyName => propertyName == "*");

            Console.WriteLine(query.QueryString);
            Console.WriteLine(new string('=', query.QueryString.Length));

            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
            using (ManagementObjectCollection searchResultCollection = searcher.Get())
            {
                // ManagementObjectCollection doesn't support indexing; this is the
                // least-ugly, least-verbose way to enumerate it with an index variable
                ManagementObject[] searchResultArray = searchResultCollection.Cast<ManagementObject>().ToArray();

                for (int i = 0; i < searchResultArray.Length; i++)
                    using (ManagementObject searchResult = searchResultArray[i])
                    {
                        Console.WriteLine($"{className}[{i}].Path.RelativePath: {searchResult.Path.RelativePath}");
                        Console.WriteLine($"{className}[{i}].Properties.Count: {searchResult.Properties.Count}");
                        foreach (PropertyData property in searchResult.Properties)
                            if (allPropertiesSelected
                                    || selectedProperties.Contains(property.Name, StringComparer.OrdinalIgnoreCase)
                            )
                            {
                                object displayValue = property.Value ?? "<null>";

                                Console.WriteLine($"{className}[{i}].Properties[\"{property.Name}\"]: {displayValue}");
                            }

                        try
                        {
                            object methodResult = searchResult.InvokeMethod(methodName, methodArguments);

                            Console.WriteLine($"{className}[{i}].{methodName}() completed with result {methodResult}.");
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"{className}[{i}].{methodName}() failed with {ex}.");
                        }
                        Console.WriteLine();
                    }
            }
        }
    }
}

...并产生这个输出...

Key properties for class Win32_Product: IdentifyingNumber, Name, Version

select * from Win32_Product where Name = 'Microsoft .NET Framework 4.8 SDK'
===========================================================================
Win32_Product[0].Path.RelativePath: Win32_Product.IdentifyingNumber="{949C0535-171C-480F-9CF4-D25C9E60FE88}",Name="Microsoft .NET Framework 4.8 SDK",Version="4.8.03928"
Win32_Product[0].Properties.Count: 27
Win32_Product[0].Properties["AssignmentType"]: 1
Win32_Product[0].Properties["Caption"]: Microsoft .NET Framework 4.8 SDK
Win32_Product[0].Properties["Description"]: Microsoft .NET Framework 4.8 SDK
Win32_Product[0].Properties["HelpLink"]: <null>
Win32_Product[0].Properties["HelpTelephone"]: <null>
Win32_Product[0].Properties["IdentifyingNumber"]: {949C0535-171C-480F-9CF4-D25C9E60FE88}
Win32_Product[0].Properties["InstallDate"]: 20191001
Win32_Product[0].Properties["InstallDate2"]: <null>
Win32_Product[0].Properties["InstallLocation"]: <null>
Win32_Product[0].Properties["InstallSource"]: C:\ProgramData\Microsoft\VisualStudio\Packages\Microsoft.Net.4.8.SDK,version=4.8.3928.1\
Win32_Product[0].Properties["InstallState"]: 5
Win32_Product[0].Properties["Language"]: 1033
Win32_Product[0].Properties["LocalPackage"]: C:\WINDOWS\Installer\34d24bd7.msi
Win32_Product[0].Properties["Name"]: Microsoft .NET Framework 4.8 SDK
Win32_Product[0].Properties["PackageCache"]: C:\WINDOWS\Installer\34d24bd7.msi
Win32_Product[0].Properties["PackageCode"]: {CC6C9CC4-DDCD-4C14-81E1-4007EE49D7C0}
Win32_Product[0].Properties["PackageName"]: sdk_tools48.msi
Win32_Product[0].Properties["ProductID"]: <null>
Win32_Product[0].Properties["RegCompany"]: <null>
Win32_Product[0].Properties["RegOwner"]: <null>
Win32_Product[0].Properties["SKUNumber"]: <null>
Win32_Product[0].Properties["Transforms"]: <null>
Win32_Product[0].Properties["URLInfoAbout"]: <null>
Win32_Product[0].Properties["URLUpdateInfo"]: <null>
Win32_Product[0].Properties["Vendor"]: Microsoft Corporation
Win32_Product[0].Properties["Version"]: 4.8.03928
Win32_Product[0].Properties["WordCount"]: 0
Win32_Product[0].Uninstall() completed with result 0.

select PackageName,Vendor,Version from Win32_Product where Name = 'Microsoft .NET Framework 4.8 SDK'
====================================================================================================
Win32_Product[0].Path.RelativePath: 
Win32_Product[0].Properties.Count: 3
Win32_Product[0].Properties["PackageName"]: sdk_tools48.msi
Win32_Product[0].Properties["Vendor"]: Microsoft Corporation
Win32_Product[0].Properties["Version"]: 4.8.03928
Win32_Product[0].Uninstall() failed with System.InvalidOperationException: Operation is not valid due to the current state of the object.
   at System.Management.ManagementObject.InvokeMethod(String methodName, Object[] args)
   at SO49798851.Program.FindAndInvoke(String className, String condition, String[] selectedProperties, String methodName, Object[] methodArguments) in ...\Program.cs:line 90.

select PackageName,Vendor,Version,IdentifyingNumber,Name from Win32_Product where Name = 'Microsoft .NET Framework 4.8 SDK'
===========================================================================================================================
Win32_Product[0].Path.RelativePath: Win32_Product.IdentifyingNumber="{949C0535-171C-480F-9CF4-D25C9E60FE88}",Name="Microsoft .NET Framework 4.8 SDK",Version="4.8.03928"
Win32_Product[0].Properties.Count: 5
Win32_Product[0].Properties["IdentifyingNumber"]: {949C0535-171C-480F-9CF4-D25C9E60FE88}
Win32_Product[0].Properties["Name"]: Microsoft .NET Framework 4.8 SDK
Win32_Product[0].Properties["PackageName"]: sdk_tools48.msi
Win32_Product[0].Properties["Vendor"]: Microsoft Corporation
Win32_Product[0].Properties["Version"]: 4.8.03928
Win32_Product[0].Uninstall() completed with result 0.

以下是这三个尝试的要点......

  1. 当然,选择所有属性会导致方法调用成功,但我们最终得到的属性比我们想要的要多得多。
  2. Selecting exactly the properties we want - but not all Key properties - results in a failed method invocation.
    • 请注意,即使其中之一Key特性,Version,是我们查询的一部分,searchResult.Path财产 https://learn.microsoft.com/dotnet/api/system.management.managementobject.path在本例中为空,这明确表明我们的结果对象有些问题。
  3. Selecting exactly the properties we want plus the Key properties results in a successful method invocation with no extraneous properties.
    • 如果我们有我们想要的属性集合(即displayProperties)和一个集合Key属性(即keyProperties), the Union()LINQ方法 https://learn.microsoft.com/dotnet/api/system.linq.enumerable.union可以轻松地将它们组合起来以获得最少的属性选择。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 WMI 获取方法 的相关文章

随机推荐