我有一个带有功能的模块,该功能使用库中的HPRESTCmdlets模块收集HP服务器上的固件版本。该函数为对象分配一个类型名称“Hardware.Firmware”。我正在使用ps1xml进行自定义查看。
该功能由Begin
,Process
和End
脚本块组成。当针对一组对象运行该函数时(通过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
答案 0 :(得分:1)
在PetSerAl上面设置ps1xml中的列宽确实解决了问题。原因是,当你有一个自定义格式并且你没有指定宽度时,PowerShell必须等到它看到每个对象,这样才能找出尝试和制作每个列的宽度。
除了宽度,命令在管道Get-HPFirmware |上看起来像这样格式表-Autosize |的Out-Default。自动调整大小会阻塞管道上的输出,直到达到Out-Default。