2017-08-16 42 views
-1

我有一个模块,其功能是使用库上的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 
+1

在格式文件中设置显式列宽。或者不要将表格格式用作类型的默认格式。 – PetSerAl

+0

添加宽度有帮助,但为什么?根据msdn宽度是可选的。 – jrob24

+0

因为没有它,格式表必须评估每列的宽度。这通常意味着在收到任何输出之前,您必须等待所有*处理完成。您也可以在使用该功能之前取出导入模块并执行该操作,这也会导致延迟。 – brendan62269

回答

1

为了PetSerAl的信用上面设置ps1xml内的列宽确实解决了问题。之所以这样,是因为当你有自定义格式并且没有指定宽度时,PowerShell必须等到它看到每个对象时,才能确定每个对象的宽度。

在输出流水线上,命令看起来像这样Get-HPFirmware |格式 - 表 - 外部化|的Out-Default。 Autosize会阻塞管道上的输出,直到达到Out-Default。