自定义 TypeNames 输出缓慢

Custom TypeNames Slow Output

我有一个模块,其功能是使用图库中的 HPRESTCmdlets 模块收集 HP 服务器上的固件版本。该函数为对象分配了一个 'Hardware.Firmware' 的类型名称。我正在使用 ps1xml 进行自定义查看。

该函数由 BeginProcessEnd 脚本块组成。当 运行 针对一组对象的函数(通过 foreach)时,第一个对象总是延迟输出到控制台,它实际上在 End 块运行之后显示。每个顺序对象都按预期运行。如果 运行 针对单个对象,我也会收到相同的延迟。

如果我删除自定义类型名,第一个对象没有延迟并且被正确处理。关于为什么在使用自定义类型时处理第一个对象有延迟以及我如何避免它有什么想法吗?

函数代码如下:

function Get-HPFirmware {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [Alias('Name', 'Server', 'Ip')]
        [string]$iLoName,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullorEmpty()]
        [Alias('User')]
        [System.Management.Automation.PSCredential][System.Management.Automation.Credential()]
        $Credential,

        [switch]$IgnoreCertFailures
    )

    Begin {
        $DefaultVariables = $(Get-Variable).Name
        try {
            Import-Module -Name HPRESTCmdlets -Force -ErrorAction Stop -Verbose:$false
        } catch {
            throw
        }

        Write-Verbose -Message "Splatting parameters for Connect-HPREST"
        $ConnectParams = @{
            'Address'  = $PSBoundParameters['iLoName']
            'Credential' = $PSBoundParameters['Credential']
        }

        if ($PSBoundParameters.ContainsKey('IgnoreCertFailures')) {
            $ConnectParams.DisableCertificateAuthentication = $true
        }
    }
    Process {
        try {
            Write-Verbose -Message "Connecting to $($ConnectParams['Address'])"
            $Session = Connect-HPREST @ConnectParams -ErrorAction Stop
        } catch {
            throw
        }

        try {
            $Systems = Get-HPRESTDataRaw -Href '/rest/v1/Systems' -Session $Session -ErrorAction Stop
            foreach ($Sys in $Systems.links.member.href) {
                $Data = Get-HPRESTDataRaw -Href $Sys -Session $Session -ErrorAction Stop
                $FirmwareUri = ($Data.Oem.Hp.links.PSObject.Members | Where-Object -FilterScript { $_.Name -match 'Firmware' }).Value.href
                Write-Verbose -Message "Firmware Uri ($FirmwareUri) discovered"
                if ($FirmwareUri) {
                    $FirmwareData = Get-HPRESTDataRaw -Href $FirmwareUri -Session $Session -ErrorAction Stop
                    if ($FirmwareData) {
                        $Firmware = $FirmwareData.Current | ForEach-Object -Process {
                            ($_.PSObject.Members | Where-Object -FilterScript { $_.MemberType -eq 'NoteProperty' }).Value
                        }
                        Write-Verbose -Message "$($Firmware.Count) components discovered"
                    } else {
                        Write-Warning -Message "No firmware data available via $FirmwareUri for $($PSBoundParameters['iLoName'])"
                        break
                    }
                } else {
                    Write-Warning -Message "Unable to locate the firmware uri"
                    break
                }

                $PCIDevicesUri = ($Data.Oem.Hp.links.PSObject.Members | Where-Object -FilterScript { $_.Name -match 'PCIDevices' }).Value.href
                Write-Verbose -Message "PCI Device Uri ($PCIDevicesUri) discovered"
                if ($PCIDevicesUri) {
                    $PCIData = Get-HPRESTDataRaw -Href $PCIDevicesUri -Session $Session -ErrorAction Stop
                    if (!$PCIData) {
                        Write-Warning -Message "No PCI device data available via $PCIDevicesUri for $($PSBoundParameters['iLoName'])"
                        break
                    }
                    Write-Verbose -Message "$($PCIData.Items.Count) devices discovered"
                } else {
                    Write-Warning -Message "Unable to locate the PCI device uri"
                    break
                }

                foreach ($i in $Firmware) {
                    if ($i.UEFIDevicePaths) {
                        $Device = $PCIData.Items | Where-Object -FilterScript { $_.UEFIDevicePath -eq $i.UEFIDevicePaths }
                        $Props = @{
                            'ElementName'    = $i.Name
                            'Location'         = $i.Location
                            'VersionString'  = $i.VersionString
                            'FQDD'             = if ($i.Name -match 'FC') { $Device.StructuredName -replace "^\w{3}", "FC" } else { $Device.StructuredName -replace "\s", "" }
                            'DeviceId'         = $Device.DeviceId
                            'SubDeviceId'    = $Device.SubsystemDeviceID
                            'VendorId'         = $Device.VendorID
                            'SubVendorId'    = $Device.SubsystemVendorID
                        }
                    } else {
                        $Props = @{ }
                        switch -wildcard ($i.Name) {
                            '*Power Supply*' {
                                $Props.ElementName = "$($i.Name).$($i.Location)"
                                $Props.Location = $i.Location
                                $Props.VersionString = $i.VersionString
                                $Props.FQDD = "PSU.$($i.Location -replace '\s', '')"
                            }
                            '*iLo*' {
                                $Props.ElementName = "Integrated Lights Out"
                                $Props.Location = $i.Location
                                $Props.VersionString = $i.VersionString.Split(' ')[0]
                                $Props.FQDD = "$($i.Name).$($i.Location -replace '\s', '')"
                            }
                            '*System ROM*' {
                                $Props.ElementName = $i.Name
                                $Props.Location = $i.Location
                                $Props.VersionString = $i.VersionString.Split(' ')[1]
                                $Props.FQDD = "BIOS.$($i.Location -replace '\s', '')"
                            }
                            '*Intelligent*' {
                                $Props.ElementName = $i.Name
                                $Props.Location = $i.Location
                                $Props.VersionString = $i.VersionString
                                $Props.FQDD = "DriverPack.$($i.Location -replace '\s', '')"
                            }
                            '*Power Management*' {
                                $Props.ElementName = $i.Name
                                $Props.Location = $i.Location
                                $Props.VersionString = $i.VersionString
                                $Props.FQDD = "DriverPack.$($i.Location -replace '\s', '')"
                            } '*Server Platform*' {
                                $Props.ElementName = $i.Name
                                $Props.Location = $i.Location
                                $Props.VersionString = $i.VersionString
                                $Props.FQDD = "SPS.$($i.Location -replace '\s', '')"
                            } '*Logic Device*' {
                                $Props.ElementName = $i.Name
                                $Props.Location = $i.Location
                                $Props.VersionString = $i.VersionString.Split(' ')[-1]
                                $Props.FQDD = "SPLD.$($i.Location -replace '\s', '')"
                            }
                            default {
                                $Props.ElementName = $i.Name
                                $Props.Location = $i.Location
                                $Props.VersionString = $i.VersionString
                                $Props.FQDD = "Unknown.$($i.Location -replace '\s', '')"
                            }
                        }
                    }
                    $Object = New-Object -TypeName System.Management.Automation.PSObject -Property $Props
                    $Object.PSObject.TypeNames.Insert(0,'Hardware.Firmware')
                    $Object
                }
            }
            Write-Verbose -Message "Disconnecting from iLo"
            Disconnect-HPREST -Session $Session
        } catch {
            Disconnect-HPREST -Session $Session
            throw
        }
    }
    End {
        Write-Verbose -Message "Cleaning up variables created by cmdlet"
        ((Compare-Object -ReferenceObject (Get-Variable).Name -DifferenceObject $DefaultVariables).InputObject) | ForEach-Object -Process {
            Remove-Variable -Name $_ -Force -ErrorAction Ignore
        }
    }
}

这是 ps1xml:

<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
    <ViewDefinitions>
        <View>
            <Name>Hardware.Firmware</Name>
            <ViewSelectedBy>
                <TypeName>Hardware.Firmware</TypeName>
            </ViewSelectedBy>
            <TableControl>
                <TableHeaders>
                    <TableColumnHeader>
                        <Label>Name</Label>
                    </TableColumnHeader>
                    <TableColumnHeader>
                        <Label>Version</Label>
                    </TableColumnHeader>
                </TableHeaders>
                <TableRowEntries>
                    <TableRowEntry>
                        <TableColumnItems>
                            <TableColumnItem>
                                <PropertyName>ElementName</PropertyName>
                            </TableColumnItem>
                            <TableColumnItem>
                                <PropertyName>VersionString</PropertyName>
                            </TableColumnItem>
                        </TableColumnItems>
                    </TableRowEntry>
                 </TableRowEntries>
            </TableControl>
        </View>
    </ViewDefinitions>
</Configuration>

这里是示例详细输出:

VERBOSE: Splatting parameters for Connect-HPREST
VERBOSE: Connecting to x.x.x.x
VERBOSE: Firmware Uri (/rest/v1/Systems/1/FirmwareInventory) discovered
VERBOSE: 19 components discovered
VERBOSE: PCI Device Uri (/rest/v1/Systems/1/PCIDevices) discovered
VERBOSE: 13 devices discovered

VERBOSE: Disconnecting from iLo
VERBOSE: Cleaning up variables created by cmdlet (This is the END block)
Name                                           Version
-----------                                    -------------
Smart HBA H240ar                               4.52
HP StorageWorks 82Q 8Gb PCI-e Dual Port FC HBA 08.02.00
HP StorageWorks 82Q 8Gb PCI-e Dual Port FC HBA 08.02.00
HP Ethernet 1Gb 4-port 331i Adapter            17.4.41
HP Ethernet 10Gb 2-port 530T Adapter           7.14.79

感谢 PetSerAl,在 ps1xml 中设置列​​宽确实解决了问题。原因是,当您有自定义格式并且没有指定宽度时,PowerShell 必须等到它看到每个对象,以便它可以计算出尝试制作每列的宽度。

没有宽度,管道上的命令看起来像这样 Get-HPFirmware |格式-Table -Autosize |超出默认值。 Autosize 会阻止管道上的输出,直到达到 Out-Default。