如何从 WMI 获取方法



tl;博士为了获得方法,我应该SELECT什么而不是*

更多信息:

下面是一个示例:

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

如果我只要求一个属性是不够的 - 我在尝试obj.InvokeMethod(...);时得到一个例外。

如果我要求*这就足够了,但如果可能的话,我宁愿避免这样做。

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

编辑

有人建议使用管理类而不是ManagementObjectSearcher。这是否加载所有属性,如*?(如果没有,这是一个很好的答案。尽管在我的实际情况下,除了调用方法的能力之外,我还需要一个属性。我的理论问题仍然存在 - 不仅仅是*全部

至于标题和TL;DR 询问,无法通过SELECT查询方法,但您可以使用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($"tt{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($"tt{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
...

除非"get 方法"的含义与我认为的不同(与调用方法不同),否则问题的其余部分似乎完全处理其他事情,即在调用方法之前填充Key属性的必要性。 我相信这在您的另一个问题中得到了解决,为什么 WMI 通过搜索而不是直接工作?

如果您真正要问的是"如何确定调用方法所需的最小属性集?",那么您也可以使用ManagementClass来实现。 该最小属性集是具有Key限定符的所有属性,因此您将使用Properties属性查找其Qualifiers属性包含Name"Key"的限定符的任何属性。

考虑Win32_Product类,它表示 Windows 安装程序安装的产品,并且(在我的 Windows 10 系统上确定,与文档不同)具有以下Key属性...

  • IdentifyingNumber
  • Name
  • Version

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

  • PackageName
  • Vendor
  • Version

。然后调用Name"Microsoft .NET Framework 4.8 SDK"的产品的Uninstall()方法。 以下代码显示了尝试此任务的三种不同方法...

  1. 选择所有属性并调用该方法。
  2. 仅选择要显示的属性并调用该方法。
  3. 选择要显示的属性以及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:ProgramDataMicrosoftVisualStudioPackagesMicrosoft.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:WINDOWSInstaller34d24bd7.msi
Win32_Product[0].Properties["Name"]: Microsoft .NET Framework 4.8 SDK
Win32_Product[0].Properties["PackageCache"]: C:WINDOWSInstaller34d24bd7.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. 准确选择我们想要的属性(但不是所有Key属性)会导致方法调用失败。
    • 请注意,即使其中一个Key属性Version是我们查询的一部分,但在这种情况下searchResult.Path属性是空的,这肯定表明我们的结果对象有些不对劲。
  3. 准确选择我们想要的属性加上Key属性会导致成功的方法调用,没有多余的属性。
    • 如果我们有一个我们想要的属性集合(即displayProperties) 和Key属性的集合(即keyProperties),Union()LINQ 方法可以轻松地将它们组合在一起,以获取要选择的最小属性。

最新更新