存储:C# 等同于 PowerShell 命令

Storage: C# equivalent of PowerShell command

与此 PowerShell 命令等效的 C# 是什么?

PS C:\WINDOWS\system32> gwmi win32_DiskDrive | %{gwmi -query "ASSOCIATORS OF {$($_.__RELPATH)} where resultclass = Win32_PnpEntity" | %{gwmi -query "ASSOCIATORS OF {$($_.__RELPATH)}"}} | fl __CLASS,__RELPATH

以上命令的结果为:

...
__CLASS   : Win32_SystemDriver
__RELPATH : Win32_SystemDriver.Name="disk"

__CLASS   : Win32_ComputerSystem
__RELPATH : Win32_ComputerSystem.Name="JMR-ENG-SARAH"

__CLASS   : Win32_IDEController
__RELPATH : Win32_IDEController.DeviceID="PCI\VEN_8086&DEV_8C82&SUBSYS_79171462&REV_00\3&11583659&0&FA"

__CLASS   : CIM_DataFile
__RELPATH : CIM_DataFile.Name="c:\windows\system32\drivers\disk.sys"

__CLASS   : Win32_DiskDrive
__RELPATH : Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE1"


__CLASS   : Win32_SCSIController
__RELPATH : Win32_SCSIController.DeviceID="PCI\VEN_144D&DEV_A804&SUBSYS_A801144D&REV_00\6&381D8F6A&0&00080008"

__CLASS   : Win32_SystemDriver
__RELPATH : Win32_SystemDriver.Name="disk"

__CLASS   : Win32_ComputerSystem
__RELPATH : Win32_ComputerSystem.Name="JMR-ENG-SARAH"

__CLASS   : CIM_DataFile
__RELPATH : CIM_DataFile.Name="c:\windows\system32\drivers\disk.sys"

__CLASS   : Win32_DiskDrive
__RELPATH : Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE2"
...

我想我不明白的是 PowerShell 命令是如何运行的。我知道部分翻译。

            ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");

foreach (ManagementObject wmi_HD in searcher.Get())
{
    String driveDeviceId = wmi_HD["DeviceID"].ToString();
}

以上代码是gwmi win32_DiskDrive部分。 属性 我需要提取的内容有待讨论。我知道有一份退货清单。

我有另一个代码片段,我在其中获取与物理磁盘关联的驱动器号,它使用 ASSOCIATORS OF gwmi 查询。因此,答案应该类似于:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;

String query2 = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + driveDeviceId + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition";
foreach (ManagementObject partition in new ManagementObjectSearcher(query2).Get())
{
    foreach (ManagementObject disk in new ManagementObjectSearcher(
                "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='"
                    + partition["DeviceID"]
                    + "'} WHERE AssocClass = Win32_LogicalDiskToPartition").Get())
    {
        String diskMount = disk["Name"].ToString();
    }
}

| 只是一个嵌入式 for 循环,其中内部 wmi 查询将使用另一个循环元素的结果。我想要的查询有点复杂,有双组 | 并使用双组 {$($_.__RELPATH)}.

如何在顶部为所需的 PowerShell 脚本编写 C# 代码?

1: 折腾了好久,研究了一番,终于明白了一些。我能够自己构建问题的答案。我将答案连同解释放在这里,希望能教育其他人。至少对我来说,WMI 是相当难理解的,尤其是错综复杂的东西。

  1. 终于更新了,快来看看吧。

信不信由你,我的重大突破来了 this Microsoft web page along with help from ScryptingGuy and 关于在 WMI 查询过滤器中转义美元符号的 SO 文章。

我也意识到最后的过滤器适用于查询。等效的源代码是只提取 属性,例如:

String propDiskRelpaths = wmiDisks["__RELPATH"].ToString();

我发现大括号是 WMI 所必需的并表示一个值。美元符号仅表示外部查询的结果。内涵 ($_.__RELPATH) 是前一个查询的 __RELPATH 属性 的一种奇特表达方式。

查询首先枚举系统上的所有磁盘。第二个查询然后枚举磁盘的所有 PNP 实体(只有一个),而最后一个查询获取磁盘的所有路径关联(驱动程序层次结构)。每个查询向下钻取一个级别。

如果有人感兴趣,这里是 PowerScript 的分解,然后我找到了底部的代码。我在这里只列出一个磁盘驱动器,但目前我的系统上有 6 个驱动器:0 到 5。物理驱动器 3 如下所示。

PS C:\WINDOWS\system32> gwmi win32_DiskDrive | fl __CLASS,__RELPATH

....
__CLASS   : Win32_DiskDrive
__RELPATH : Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE3"

这是第二个命令,它为磁盘生成 PNP 实体。在这种情况下,我选择了我的 C: 驱动器,驱动器 0,而不是我的 M.2 卡,驱动器 3,在此作为示例列出。真正的代码在 for 循环中,所以我会得到所有驱动器。

PS C:\WINDOWS\system32> gwmi -query 'ASSOCIATORS OF {Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE0"} where resultclass = Win32_PnpEntity' | fl __CLASS,__RELPATH

__CLASS   : Win32_PnPEntity
__RELPATH : Win32_PnPEntity.DeviceID="SCSI\DISK&VEN_NVME&PROD_SAMSUNG_SSD_960\7&335357E&0&000000"

最后一条命令和输出是:

PS C:\WINDOWS\system32> gwmi -query 'ASSOCIATORS OF {Win32_PnPEntity.DeviceID="SCSI\DISK&VEN_NVME&PROD_SAMSUNG_SSD_960\7&335357E&0&000000"}' | fl __CLASS,__RELPATH


__CLASS   : Win32_SCSIController
__RELPATH : Win32_SCSIController.DeviceID="PCI\VEN_144D&DEV_A804&SUBSYS_A801144D&REV_00\6&381D8F6A&0&00080008"

__CLASS   : Win32_SystemDriver
__RELPATH : Win32_SystemDriver.Name="disk"

__CLASS   : Win32_ComputerSystem
__RELPATH : Win32_ComputerSystem.Name="JMR-ENG-SARAH"

__CLASS   : CIM_DataFile
__RELPATH : CIM_DataFile.Name="c:\windows\system32\drivers\disk.sys"

__CLASS   : Win32_DiskDrive
__RELPATH : Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE0"

如您所见,我的 M.2 卡被列为 SCSI 设备,而不是真正的 NVMe PCIe 卡。我进行了研究,这符合预期,因为 Microsoft StorNVMe.sys 驱动程序将 NVMe 实现为 IOCTL_SCSI_* 转换为设备驱动程序级别的 IOCTL_NVME_* 命令。这在 Windows Vista 中是正确的,显然在 Windows 10 中仍然如此。

PS C:\WINDOWS\system32> gwmi -query 'ASSOCIATORS OF {Win32_PnPEntity.DeviceID="SCSI\DISK&VEN_NVME&PROD_SAMSUNG_SSD_960\7&335357E&0&000000"}' | fl __CLASS,__RELPATH


__CLASS   : Win32_SCSIController
__RELPATH : Win32_SCSIController.DeviceID="PCI\VEN_144D&DEV_A804&SUBSYS_A801144D&REV_00\6&381D8F6A&0&00080008"

__CLASS   : Win32_SystemDriver
__RELPATH : Win32_SystemDriver.Name="disk"

__CLASS   : Win32_ComputerSystem
__RELPATH : Win32_ComputerSystem.Name="JMR-ENG-SARAH"

__CLASS   : CIM_DataFile
__RELPATH : CIM_DataFile.Name="c:\windows\system32\drivers\disk.sys"

__CLASS   : Win32_DiskDrive
__RELPATH : Win32_DiskDrive.DeviceID="\\.\PHYSICALDRIVE0"

这是我想要的最终代码。我应该补充说基于 IDE 的驱动器,然后我可以枚举 IDE class 并获得该磁盘支持的模式(IDE、AHCI、RAID 等) .

希望这个解释是清楚的。让我知道,如果它需要更多的解释。哦,下面的代码假设是VS2017或以上版本。

using System;
using System.Collections.Generic;
using System.Management;
using SiloStor.Tools;

internal static void EnumerateClassPaths()
{
    try
    {
        // Enumerate all disk drives.
        ManagementObjectSearcher oSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
        foreach (ManagementObject wmiDisks in oSearcher.Get())
        {
            // Get the properties needed.
            String propDiskRelpaths = wmiDisks["__RELPATH"].ToString();

            // 
            String wmiQuery1 = "ASSOCIATORS OF {" + propDiskRelpaths + "} WHERE ResultClass = Win32_PnpEntity";
            foreach (ManagementObject wmiPnp in new ManagementObjectSearcher(wmiQuery1).Get())
            {
                // Get the properties needed.
                String propPnpRelpaths = wmiPnp["__RELPATH"].ToString();

                // 
                String wmiQuery2 = "ASSOCIATORS OF {" + propPnpRelpaths + "}";
                foreach (ManagementObject wmiDrivers in new ManagementObjectSearcher(wmiQuery2).Get())
                {
                    String driverClass = wmiDrivers["__CLASS"].ToString();
                    String driverRelpath = wmiDrivers["__RELPATH"].ToString();
                    Console.WriteLine($"__CLASS   : {driverClass}");
                    Console.WriteLine($"__RELPATH : {driverRelpath}");
                    Console.WriteLine("");
                }
            }
        }
    }

    catch (Exception ex)
    {
        // Log the error.
        Errors.LogError(ex);
    }
}

更新:

昨天(2017年8月9日),我找到了一个link微软WMI Code Creatorv1.0。我没有收到 Microsoft 的报酬,我也不认为这个工具是 WMI 工作的 "Must Have",但它实际上非常好,根本没有做广告。

WMI Code Creator,为应用程序提供源代码,为 WMI 查询生成 C# 和 VB.Net 源代码。遗憾的是,WMI 查询仅限于基本命令,但仍然非常有用。另一个有用的是该工具显示了用户可以查询的 classes,也很有帮助。遗憾的是,没有 ASSOCIATORS OF 或串联查询,但确实有许多其他有用的功能。检查一下,希望对您有所帮助。