存储:C#相当于PowerShell命令

Sar*_*ger 3 c# powershell wmi storage

什么是与此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
Run Code Online (Sandbox Code Playgroud)

上述命令的结果是:

...
__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"
...
Run Code Online (Sandbox Code Playgroud)

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

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

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

上面的代码是gwmi win32_DiskDrive部分.我需要提取的属性可供讨论.我知道有一份归还房产的清单.

我有另一个代码片段,我得到与物理磁盘相关的驱动器号,它使用ASSOCIATORS OFgwmi查询.因此,答案应该类似于:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

|被简单地嵌入的for循环,其中内WMI查询将使用其它环形元件的结果.我想要的查询有点复杂,使用双组|并使用双组{$($_.__RELPATH)}.

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

Sar*_*ger 5

1:我挣扎了很长时间并进行了研究,最后对事情有所了解.我能够自己构建问题的答案.我在这里给出答案以及希望教育他人的解释.至少对我来说,WMI很难理解,尤其是错综复杂的情况.

  1. 最后更新,检查出来.

我的重大突破来自于相信这个微软网页以及ScryptingGuy的帮助以及关于在WMI查询过滤器中逃避美元符号的这篇 SO文章.

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

String propDiskRelpaths = wmiDisks["__RELPATH"].ToString();
Run Code Online (Sandbox Code Playgroud)

我发现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"
Run Code Online (Sandbox Code Playgroud)

这是第二个命令,它产生磁盘的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"
Run Code Online (Sandbox Code Playgroud)

最后一个命令和输出是:

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"
Run Code Online (Sandbox Code Playgroud)

如您所见,我的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"
Run Code Online (Sandbox Code Playgroud)

这是我想要的最终代码.我应该添加基于IDE的驱动器,然后我可以枚举IDE类并获得该磁盘支持的模式(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);
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:

昨天(2017年8月9日),我找到了一个指向 Microsoft WMI Code Creatorv1.0 的链接.我没有被微软支付,也不认为这个工具对于WMI工作来说是"必须拥有的",但它实际上相当不错而且根本没有做广告.

WMI Code Creator,为此,给出了源代码到App,生成C#和VB.Net源代码WMI查询.遗憾的是,WMI查询仅限于基本命令,但仍然非常有用.另一个有用的东西是该工具显示用户可以查询的类,也非常有用.遗憾的是,没有ASSOCIATORS OF或连接的查询,但确实有许多其他有用的功能.检查出来,希望它有所帮助.