自定义TypeNames慢速输出

时间:2017-08-16 19:58:52

标签: powershell typename

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

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

如果删除自定义typename,则第一个对象没有延迟并且处理正确。关于为何在使用自定义类型时处理第一个对象有延迟的任何想法,我该如何避免?

以下是该函数的代码:

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

1 个答案:

答案 0 :(得分:1)

在PetSerAl上面设置ps1xml中的列宽确实解决了问题。原因是,当你有一个自定义格式并且你没有指定宽度时,PowerShell必须等到它看到每个对象,这样才能找出尝试和制作每个列的宽度。

除了宽度,命令在管道Get-HPFirmware |上看起来像这样格式表-Autosize |的Out-Default。自动调整大小会阻塞管道上的输出,直到达到Out-Default。