在输出报告中显示列 Headers 一次

Displaying Column Headers Once in Output Report

我正在使用 PowerCLI 编写一个脚本来审计公司虚拟环境中的磁盘分区类型。到目前为止我得到了这个代码:

$report = @()

$VMs = (Get-VM).where{$_.PowerState -eq 'PoweredOn' -and $_.Guest.OSFullName -match 'Windows'}

foreach ($VM in $VMs){
    $vmName = $VM.Name
    $output = Invoke-VMScript -ScriptText @'
      Get-Disk | 
        select @{ l="ComputerName"; e={ $env:COMPUTERNAME } },
               Number, 
               @{ name='Size'; expr={[int]($_.Size/1GB)} },
               PartitionStyle
'@ -VM $vmName -GuestUser $Username -GuestPassword $Password

    $output.ScriptOutput #printing each for testing
    $report += $output.ScriptOutput
}
$report | FT -AutoSize

这将产生如下所示的输出:

ComputerName Number Size PartitionStyle
VMNAME1 0 100 MBR
VMNAME1 1 20 GPT
VMNAME1 2 20 MBR
ComputerName Number Size PartitionStyle
VMNAME2 0 100 MBR
VMNAME2 1 20 GPT

我面临的问题是输出报告中每个虚拟机都重复了 headers 列。我怎样才能解决这个问题,只显示一次 headers 列,如下所示:

ComputerName Number Size PartitionStyle
VMNAME1 0 100 MBR
VMNAME1 1 20 GPT
VMNAME1 2 20 MBR
VMNAME2 0 100 MBR
VMNAME2 1 20 GPT

关于如何执行此操作的任何想法?我是 Powershell 的新手,所以我不知道该怎么做。

由于 ScriptOutput 的输出是字符串,您必须自己解析它。相反,我建议将其转换为适合作为文本传递的格式,例如 CSV。

$VMs = (Get-VM).where{$_.PowerState -eq 'PoweredOn' -and $_.Guest.OSFullName -match 'Windows'}

$report = foreach ($VM in $VMs){
    $vmName = $VM.name
    $output = Invoke-VMScript -ScriptText @'
      Get-Disk | 
        select @{ l="ComputerName"; e={ $env:COMPUTERNAME } },
               Number, 
               @{ name='Size'; expr={[int]($_.Size/1GB)} },
               PartitionStyle | ConvertTo-Csv
'@ -VM $vmName -GuestUser $Username -GuestPassword $Password

    $output.ScriptOutput | ConvertFrom-Csv
}

$report | FT -AutoSize

此外,正如 Theo 评论的那样,+= 可能非常昂贵,而且几乎总是不必要的。如此处所示,您可以简单地将 foreach 的输出直接收集到变量中。

编辑

由于任何额外的输出(例如错误)都与您想要的数据一起被捕获,因此可能会导致您提到的额外空白行。我能够克服这个问题的一种方法是检查列 header 是否存在,然后去除之前的任何垃圾。

$VMs = (Get-VM).where{$_.PowerState -eq 'PoweredOn' -and $_.Guest.OSFullName -match 'Windows'}

$report = foreach ($VM in $VMs){
    $output = Invoke-VMScript -ScriptText @'
        Get-Disk | Foreach-Object{
            [PSCustomObject]@{
                ComputerName   = $env:COMPUTERNAME
                Number         = $_.number
                Size           = [int]($_.size/1GB)
                PartitionStyle = $_.PartitionStyle
            }
        } | ConvertTo-Csv -NoTypeInformation

'@ -VM $vm.Name -GuestUser $Username -GuestPassword $Password

    if($output.ScriptOutput -match 'PartitionStyle')
    {
        $output.ScriptOutput -replace '(?s)^.+(?="Com)' | ConvertFrom-Csv
    }
}

$report | FT -AutoSize