Powershell:如何结合 2 个命令的输出将磁盘字母与磁盘 MediaType 相关联?

Posted

技术标签:

【中文标题】Powershell:如何结合 2 个命令的输出将磁盘字母与磁盘 MediaType 相关联?【英文标题】:Powershell: How to combine the output of 2 commands to associate disk letter with disk MediaType? 【发布时间】:2021-10-23 06:22:46 【问题描述】:

我正在使用以下命令获取磁盘信息:

get-ciminstance -ClassName Win32_LogicalDisk

问题是,它不包含MediaType 属性(HDD、SSD 或分别为数字形式 4、3)。

我想我需要将它与另一个命令结合(关联),例如:

Get-PhysicalDiskGet-WmiObject -Class MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage

我从 Node.js 调用这些命令,因此我可以运行单独的命令并在之后组合结果。它不必是 1 个命令。我只是不确定如何关联它们,因为 Powershell API 不一致:

这个返回数字

(Get-WmiObject -Class MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage).DeviceID

这个返回驱动器号

(get-ciminstance -ClassName Win32_LogicalDisk).DeviceID

我在另一个thread 中找到了这段代码,但我不确定如何在其中添加MediaType 属性:

Get-WmiObject Win32_DiskDrive | ForEach-Object 
  $disk = $_
  $partitions = "ASSOCIATORS OF " +
                "Win32_DiskDrive.DeviceID='$($disk.DeviceID)' " +
                "WHERE AssocClass = Win32_DiskDriveToDiskPartition"
  Get-WmiObject -Query $partitions | ForEach-Object 
    $partition = $_
    $drives = "ASSOCIATORS OF " +
              "Win32_DiskPartition.DeviceID='$($partition.DeviceID)' " +
              "WHERE AssocClass = Win32_LogicalDiskToPartition"
    Get-WmiObject -Query $drives | ForEach-Object 
      New-Object -Type PSCustomObject -Property @
        Disk        = $disk.DeviceID
        DiskSize    = $disk.Size
        DiskModel   = $disk.Model
        Partition   = $partition.Name
        RawSize     = $partition.Size
        DriveLetter = $_.DeviceID
        VolumeName  = $_.VolumeName
        Size        = $_.Size
        FreeSpace   = $_.FreeSpace
      
    
  

【问题讨论】:

你确定,这会返回 MediaType 吗? Get-CimInstance -ClassName Win32_LogicalDisk | Select-Object -Property MediaType @jfrmilner 是的,但这是一个错误的 MediaType,它返回一些神奇的数字 12,而不是 3 (SSD) 或 4 (HDD)。 【参考方案1】:

我不知道是否有更复杂的方法,但我认为它提供了您期望的结果。

$PhysicalDiskList = 
    Get-PhysicalDisk
$LogicalDiskList = 
    Get-CimInstance -ClassName CIM_LogicalDisk | 
        Where-Object -Property 'DriveType' -EQ -Value 3
$Result = 
foreach ($LogicalDisk in $LogicalDiskList) 
    $DiskPartition = 
        Get-CimAssociatedInstance -InputObject $LogicalDisk -ResultClass CIM_DiskPartition
    $PhysicalDisk = 
        $PhysicalDiskList | 
            Where-Object -Property 'DeviceID' -EQ -Value $DiskPartition.DiskIndex
    [PSCustomObject]@
        DriveLetter = $LogicalDisk.DeviceID
        VolumeName  = $LogicalDisk.VolumeName
        Size        = $LogicalDisk.Size
        FreeSpace   = $LogicalDisk.FreeSpace
        DriveModel  = $PhysicalDisk.FriendlyName
        MediaType   = $PhysicalDisk.MediaType
    


$Result | 
    Format-Table -AutoSize

它在我的系统上返回以下内容:

DriveLetter VolumeName          Size    FreeSpace DriveModel                 MediaType
----------- ----------          ----    --------- ----------                 ---------
C:          System      254493077504  49397727232 SAMSUNG MZNTY256HDHP-000L7 SSD
D:          Data       1000067821568 643155914752 WDC WD10SPCX-08S8TT0       HDD

【讨论】:

感谢您的回答。不幸的是,只有 SSD 驱动器具有正确的MediaType: SSD。 HDD 驱动器有一个空的MediaType: ''。你知道为什么会这样吗?当我单独运行 Get-PhysicalDisk 时,我得到所有驱动器的正确结果。 我不知道该说什么。它按预期对我有用。 我的硬盘有 2 个分区和一个网络文件夹映射在上面,也许这就是导致硬盘出现问题的原因?如果我删除-Value $DiskPartition.DiskIndex 之后的所有内容并将$PhysicalDisk 放在它下面,它只会返回SSD 驱动器。但是上面几行的$PhysicalDisk 会返回来自所有驱动器的所有分区 我更改了代码以仅获取固定磁盘 - 没有 DVD 驱动器或网络驱动器。但是多个分区应该不是问题。我试过了,它只是为这个磁盘上的两个分区返回相同的硬件信息两次。 谢谢,不幸的是,这个解决方案不适用于我的用例。我确实需要所有驱动器的列表,包括网络驱动器。顺便说一句,由于某种原因,编辑后的 ​​sn-p 仍然没有为 HDD 驱动器返回 MediaType: 'HDD'【参考方案2】:

在获取 mediatype 和其他属性方面,我的结果好坏参半。一些系统返回实际值,而另一些系统则返回整数。这是我的脚本中的一个 sn-p,可以帮助您解决这个问题。

Get-CimInstance Win32_Diskdrive -Filter "Partitions>0" | ForEach-Object 
    $disk = Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage -Filter "SerialNumber='$($_.SerialNumber.trim())'"

    foreach($partition in $_ | Get-CimAssociatedInstance -ResultClassName Win32_DiskPartition)
        foreach($logicaldisk in $partition | Get-CimAssociatedInstance -ResultClassName Win32_LogicalDisk)
            [PSCustomObject]@
                Disk          = $_.DeviceID
                DiskModel     = $_.Model
                DiskSize      = $_.Size
                HealthStatus  = $disk.HealthStatus
                BusType       = $disk.BusType
                MediaType     = "0 (1)" -f $_.MediaType,$disk.MediaType
                Partition     = $partition.Name
                PartitionSize = $partition.Size
                VolumeName    = $logicaldisk.VolumeName
                DriveLetter   = $logicaldisk.DeviceID
                VolumeSize    = $logicaldisk.Size
                FreeSpace     = $logicaldisk.FreeSpace
            
        
    

在返回代码的时候,可以改为运行。

$mediatypelist = @
    '0' = 'Unspecified'
    '3' = 'HDD'
    '4' = 'SSD'
    '5' = 'SCM'


$healthstatuslist = @
    '0' = 'Healthy'
    '1' = 'Warning'
    '2' = 'Unhealthy'
    '5' = 'Unknown'


$bustypelist = @
    '0' = 'Unknown'
    '1' = 'SCSI'
    '2' = 'ATAPI'
    '3' = 'ATA'
    '4' = 'IEEE 1394'
    '5' = 'SSA'
    '6' = 'Fibre Channel'
    '7' = 'USB'
    '8' = 'RAID'
    '9' = 'iSCSI'
    '10' = 'Serial Attached SCSI (SAS)'
    '11' = 'Serial ATA (SATA)'
    '12' = 'Secure Digital (SD)'
    '13' = 'Multimedia Card (MMC)'
    '14' = 'This value is reserved for system use.'
    '15' = 'File-Backed Virtual'
    '16' = 'Storage Spaces'
    '17' = 'NVMe'
    '18' = 'This value is reserved for system use.'


Get-CimInstance Win32_Diskdrive -Filter "Partitions>0" | ForEach-Object 
    $disk = Get-CimInstance -ClassName MSFT_PhysicalDisk -Namespace root\Microsoft\Windows\Storage -Filter "SerialNumber='$($_.SerialNumber.trim())'"

    foreach($partition in $_ | Get-CimAssociatedInstance -ResultClassName Win32_DiskPartition)
        foreach($logicaldisk in $partition | Get-CimAssociatedInstance -ResultClassName Win32_LogicalDisk)
            [PSCustomObject]@
                Disk          = $_.DeviceID
                DiskModel     = $_.Model
                DiskSize      = $_.Size
                HealthStatus  = $healthstatuslist["$($disk.HealthStatus)"]
                BusType       = $bustypelist["$($disk.BusType)"]
                MediaType     = "0 (1)" -f $_.MediaType,$mediatypelist["$($disk.MediaType)"]
                Partition     = $partition.Name
                PartitionSize = $partition.Size
                VolumeName    = $logicaldisk.VolumeName
                DriveLetter   = $logicaldisk.DeviceID
                VolumeSize    = $logicaldisk.Size
                FreeSpace     = $logicaldisk.FreeSpace
            
        
    

【讨论】:

只有一个问题 - 我有一个网络驱动器 Z: 映射到我的硬盘驱动器 E: 上的一个文件夹,但是在这个 sn-p 的输出中我得到 DriveLetter : E: E:Z: 驱动器。如果我单独运行get-ciminstance -ClassName Win32_LogicalDisk,我会看到网络驱动器分配了Z: 字母。有没有办法在这个 sn-p 中解决这个问题?我认为这个问题是由Get-CimInstance -ClassName MSFT_PhysicalDisk 不返回网络驱动器引起的 我没有从get-ciminstance -ClassName Win32_LogicalDisk 获得任何映射驱动器。 $disk 中唯一使用的是 healthstatusbustypemediatype。驱动器号来自$logicaldisk.deviceid - 需要弄清楚为什么没有字母。 我认为 MSFT_PhysicalDisk 通常无法获取网络驱动器,也许这个 sn-p 应该从 Win32_LogicalDisk 获取整个驱动器列表,然后将列表从 MSFT_PhysicalDisk 以相反的方式填充到Win32_LogicalDisk的输出? 就像我说的物理磁盘只用于三个属性,没有一个是驱动器号 看来Get-CimAssociatedInstance 正在获取它映射到的网络源驱动器。也许代码 sn-p 应该改为循环 get-ciminstance -ClassName Win32_LogicalDisk 以获取所有具有正确驱动器号的驱动器并将驱动器映射到 Get-CimInstance Win32_Diskdrive 的输出?这也可以获取网络驱动器的 ProvideName 属性

以上是关于Powershell:如何结合 2 个命令的输出将磁盘字母与磁盘 MediaType 相关联?的主要内容,如果未能解决你的问题,请参考以下文章

Powershell:将外部命令输出通过管道传输到另一个外部命令

将 2 个 git 存储库与冲突结合在一起后,我希望 Powershell 中的 git mergetool 始终为每个文件选择(m)修改

适用于 Linux 的 Powershell:将命令与管道符号结合起来不起作用

如何使用 PowerShell 处理 diskpart 命令的输出

如何将所有输出流写入 PowerShell 中的变量?

我正在使用来自 python 的 powershell 命令获取一些数据,而 Windows 中没有 cmd!如何将此输出分配给字符串变量?