如何根据我认为的嵌套 属性 过滤 WMI 搜索?

How do I filter a WMI search on what I think is a nested property?

我正在使用以下命令通过 WMI 获取加载的依赖项或模块列表,但是在使我的搜索字符串正确时遇到问题,基本上我需要通过它的句柄和句柄来定位特定的依赖进程 属性 似乎嵌套在 ManagementObject.

var wmiQueryString = string.Format("select * from CIM_ProcessExecutable WHERE Dependent.Handle=\"{0}\"",procID);
using (var searcher = new ManagementObjectSearcher(string.Format(wmiQueryString)))
using (var results = searcher.Get())
{
    foreach (var item in results.Cast<ManagementObject>())
    {
        try
        {
            var dependent = new ManagementObject((string)item["Dependent"]);
            Console.WriteLine(new FileInfo((string)dependent["Name"]).FullName);
        }
        catch (System.Management.ManagementException ex)
        {
            // Process does not exist anymore
        }
    }
}

仅使用 "Dependent.Handle" 似乎不起作用,我尝试过的每个变体都导致无效查询字符串异常。我假设是因为搜索者不了解对象结构?

我可以在我的 C# 中加载和过滤数据,但出于性能原因,我想在 WMI 查询中进行过滤。

根据以下答案更新了代码:

        var wmiQueryString = string.Format("ASSOCIATORS OF {{Win32_Process.Handle=\"{0}\" }} WHERE ResultClass = CIM_ProcessExecutable", procID);
        using (var searcher = new ManagementObjectSearcher(wmiQueryString))
        using (var results = searcher.Get())
        {
            foreach (ManagementObject item in results) // This throws System.Management.ManagementException: 'Invalid object path '
            {
                foreach (PropertyData prop in item.Properties) // At this point this is just here for testing, but this is never reached anyway as the exception occurs prior to the iteration.
                {
                    Console.WriteLine("{0}: {1}", prop.Name, prop.Value);
                }

                //var dependent = item["Dependent"] as ManagementObject;
                //Console.WriteLine(new FileInfo((string)dependent["Name"]).FullName);
            }
        }

然而,这会在指示的行上抛出 System.Management.ManagementException: 'Invalid object path '。但这可能只是来自上一行,这可能仍然表示查询字符串错误。

事实证明,秘诀是 references of 而不是 associators of

var wmiQueryString = string.Format( "references of {{win32_process.Handle={0}}}", handle );
using ( var searcher = new ManagementObjectSearcher( wmiQueryString ) )
using ( var results = searcher.Get( ) )
{
  foreach ( ManagementObject item in results )
  {
    Console.WriteLine( item.ClassPath ); //--> turns out this is the cim_processexecutalbe

    //--> and these are it's properties...with references to cim_datafile...  
    foreach ( PropertyData prop in item.Properties )
    {
      Console.WriteLine( "{0}: {1}", prop.Name, prop.Value );
    }
  }
}

这将为您提供 CIM_ProcessExecutables 属性:

\CLAYDEV\root\cimv2:Win32_SessionProcess
Antecedent: \.\root\cimv2:Win32_LogonSession.LogonId="999"
Dependent: \.\root\cimv2:Win32_Process.Handle="628"
\CLAYDEV\root\cimv2:Win32_SystemProcesses
GroupComponent: \CLAYDEV\root\cimv2:Win32_ComputerSystem.Name="CLAYDEV"
PartComponent: \CLAYDEV\root\cimv2:Win32_Process.Handle="628"
\CLAYDEV\root\cimv2:CIM_ProcessExecutable
Antecedent: \CLAYDEV\root\cimv2:CIM_DataFile.Name="C:\WINDOWS\system32\winlogon.exe"
BaseAddress: 140696226496512
Dependent: \CLAYDEV\root\cimv2:Win32_Process.Handle="628"
GlobalProcessCount:
ModuleInstance: 1687814144
ProcessCount: 0
....

事实证明——正如 Mateo 在评论中指出的那样,references ofassociators of 在格式化方面有点挑剔。 {} 中不能有多余的空格。我不知道。

您也可以使用associators of。如果你得到的语法就是这样......并且你指的是 associated 类型(而不是 associated 类型)。我的意思是 CIM_ProcessExecutablesCIM_Process 关联到 CIM_DataFile。因此,要仅获取 CIM_DataFiles 属性...您可以这样做:

  var wmiQueryString = string.Format( "associators of {{win32_process.Handle={0}}} where resultclass=cim_datafile", handle );

...这会让您直接进入 CIM_DataFile 属性...

\CLAYDEV\root\cimv2:CIM_DataFile
AccessMask: 17957033
Archive: True
Caption: c:\windows\system32\winlogon.exe
Compressed: False
CompressionMethod:
CreationClassName: CIM_LogicalFile
CreationDate: 20170510121417.106825-240
CSCreationClassName: Win32_ComputerSystem
CSName: CLAYDEV
Description: c:\windows\system32\winlogon.exe
Drive: c:
EightDotThreeFileName: c:\windows\system32\winlogon.exe
Encrypted: False
EncryptionMethod:
Extension: exe
FileName: winlogon
FileSize: 707072
FileType: Application
FSCreationClassName: Win32_FileSystem
FSName: NTFS
Hidden: False
InstallDate: 20170510121417.106825-240
InUseCount:
LastAccessed: 20170510121417.106825-240
LastModified: 20170419020715.554583-240
Manufacturer: Microsoft Corporation
Name: c:\windows\system32\winlogon.exe
Path: \windows\system32\
Readable: True
Status: OK
System: False
Version: 10.0.15063.250
Writeable: True
...

只获取感兴趣的属性:

我看不出哪里有 select 来自 associators ofreferences of 语句的子集......但是正如下面评论中所建议的,你可以做一个SelectMany 以仅获取您想要的属性:

  var wmiQueryString = string.Format( "associators of {{win32_process.Handle={0}}} where resultclass=cim_datafile", handle );
  using ( var searcher = new ManagementObjectSearcher( wmiQueryString ) )
  {
    var results =
      searcher
      .Get( )
      .OfType<ManagementBaseObject>( )
      .SelectMany
      ( df => df.Properties.OfType<PropertyData>( ).Where( pd => pd.Name == "Caption" ) );

    foreach ( PropertyData item in results )
    {
      Console.WriteLine( item.Value );
    }
  }

问题是它仍然迭代整个 属性 集以获得目标 属性。直奔你想要的 属性 似乎 运行 更快:

  var wmiQueryString = string.Format( "associators of {{win32_process.Handle={0}}} where resultclass=cim_datafile", handle );
  using ( var searcher = new ManagementObjectSearcher( wmiQueryString ) )
  using ( var results = searcher.Get( ) )
  {
    foreach ( ManagementObject item in results )
    {
      Console.WriteLine( item[ "Caption" ] );
    }
  }

...但恐怕这两种方式都不是特别快。