PowerShell对象检索所有对象属性

时间:2015-07-01 07:54:26

标签: powershell object properties

我们遇到了一些奇怪的问题。我们创建的函数工作正常,并在第一个对象具有所需的所有属性时输出所有属性。如果不是这种情况,它只会将自己限制在第一个对象的输出中。

我知道这听起来有点令人困惑,但这就是我的意思:

Function Get-PrintersInstalledHC {
    Param (
        [Parameter(ValueFromPipeline)]
        [Object[]]$Servers
    )
    Process {
        foreach ($S in $Servers) {
            Try {
                if ($S.Enabled) {
                    $Printers = Get-Printer -ComputerName $S.Name -Full -EA Stop | 
                        Select-Object *, 
                            @{Name='ComputerStatus';Expression={'Ok'}}, 
                            @{Name='RetrievalDate';Expression={(Get-Date -Format "dd/MM/yyyy HH:mm")}}

                    if ($Printers) {
                        $CimParams = @{
                            ClassName    = 'Win32_PrinterConfiguration'
                            ComputerName = $S.Name
                            Property     = '*'
                            ErrorAction  = 'Stop'
                        }                
                        $Details = Get-CimInstance @CimParams

                        Foreach ($P in $Printers) {
                            Foreach($D in $Details) {
                                if ($P.Name -eq $D.Name) {
                                    $Props = @{
                                        DriverVersion = $D.DriverVersion
                                        Collate       = $D.Collate
                                        Color         = $D.Color
                                        Copies        = $D.Copies
                                        Duplex        = $D.Duplex
                                        PaperSize     = $D.PaperSize
                                        Orientation   = $D.Orientation
                                        PrintQuality  = $D.PrintQuality
                                    }
                                    $P | Add-Member -NotePropertyMembers $Props -TypeName NoteProperty -PassThru
                                    Break
                                }
                            }
                        }
                    }
                }
            }
            Catch {
                if (Test-Connection $S.Name -Count 2 -EA Ignore) {
                    [PSCustomObject]@{
                        ComputerName   = $S.Name
                        ComputerStatus = "ERROR: $($Error[0].Exception.Message)" 
                        RetrievalDate  = (Get-Date -Format "dd/MM/yyyy HH:mm")
                    }
                }
                else {
                    [PSCustomObject]@{
                        ComputerName   = $S.Name
                        ComputerStatus = 'Offline'
                        RetrievalDate  = (Get-Date -Format "dd/MM/yyyy HH:mm")
                    }
                }
            }
        }
    }
}

当第一台服务器在Get-Printer上失败并且其他服务器成功时,它只会输出ComputerNameComputerStatusRetrievalDate。像这样:

$Servers = 'SERVER1', 'SERVER2' | Get-ADComputer | Select-Object Name, Enabled
Get-PrintersInstalledHC $Servers

ComputerName                             ComputerStatus                           RetrievalDate                          
------------                             --------------                           -------------                          
SERVER1                            ERROR: The spooler service is not rea... 01/07/2015 10:21                       
SERVER2                            Ok                                       01/07/2015 10:21                       
SERVER2                            Ok                                       01/07/2015 10:21                       
SERVER2                            Ok                                       01/07/2015 10:21                       
SERVER2                            Ok                                       01/07/2015 10:21

当第一台服务器成功使用Get-Printer而其他服务器不成功时,它会输出所有对象属性。

$Servers = 'SERVER2', 'SERVER1' | Get-ADComputer | Select-Object Name, Enabled
    Get-PrintersInstalledHC $Servers

RenderingMode         : SSR
PrinterStatus         : Normal
Type                  : Local
Caption               : 
Description           : 
ElementName           : 
InstanceID            : 
CommunicationStatus   : 
DetailedStatus        : 
HealthState           : 
InstallDate           : 
Name                  : PRINTERNAME
OperatingStatus       : 
OperationalStatus     : 
PrimaryStatus         : 
Status                : 
StatusDescriptions    : 
Comment               : 
ComputerName          : SERVER2
Datatype              : RAW
DefaultJobPriority    : 0
DriverName            : Canon
JobCount              : 0
KeepPrintedJobs       : False
Location              : Corridor
PermissionSDDL        : G:SYD:(A;;LCSWSDRCWDWO;;;WD)(A;CIIO;RC;;;CO)(A;OIIO;RPWPSDRCWDWO;;;CO)(A;;LCSWSDRCWDWO;;;S-1-5-21
                        -1078081533-261478967-839522115-331680)(A;OIIO;RPWPSDRCWDWO;;;S-1-5-21-1078081533-261478967-83952
                        2115-331680)(A;;LCSWSDRCWDWO;;;BA)(A;OIIO;RPWPSDRCWDWO;;;BA)
PortName              : PORTNAME
PrintProcessor        : winprint
Priority              : 1
Published             : False
SeparatorPageFile     : 
Shared                : True
ShareName             : SHARENAME
StartTime             : 0
UntilTime             : 0
PSComputerName        : 
CimClass              : ROOT/StandardCimv2:MSFT_Printer
CimInstanceProperties : {Caption, Description, ElementName, InstanceID...}
CimSystemProperties   : Microsoft.Management.Infrastructure.CimSystemProperties
ComputerStatus        : Ok
RetrievalDate         : 01/07/2015 10:24
PaperSize             : A4 210 x 297 mm
Orientation           : 1
Collate               : True
Color                 : 2
Copies                : 1
DriverVersion         : 1606
Duplex                : False
PrintQuality          : 600

# More objects here

ComputerName   : SERVER1
ComputerStatus : ERROR: The spooler service is not reachable.  Ensure the spooler service is running.
RetrievalDate  : 01/07/2015 10:25

如何确保始终生成所有属性?因为很难预测第一台服务器是否会在Get-Printer上失败。

1 个答案:

答案 0 :(得分:2)

答案是使打印机的详细信息成为您正在创建的对象的单独属性。您的基本对象应如下所示:

ComputerName
ComputerStatus
RetrievalDate
PrinterDetails

您已经拥有的前三个,以及您当前正在做的是如果计算机可以访问,则此对象包含每个打印机的大量其他属性。

您需要做的是将大量属性放入其自己的对象中并将其附加到第四个属性。然后你可以走输出并做如果 PrinterDetails不为空。

我不完全理解ForEach$P$D中发生了什么,看起来您正在丰富这些信息从Get-Printer返回。只要$P | Add-Member被保留,您就应该能够将$Printers分配给新的PrinterDetails属性(尽管我个人可能不会进行丰富,但创建了细节本身的财产)。

Function Get-PrintersInstalledHC {
    Param (
        [Parameter(ValueFromPipeline)]
        [Object[]]$Servers
    )
    Process {
        foreach ($S in $Servers) {
            Try {
                if ($S.Enabled) {
                    $Printers = Get-Printer -ComputerName $S.Name -Full -EA Stop 

                    if ($Printers) {
                        $CimParams = @{
                            ClassName    = 'Win32_PrinterConfiguration'
                            ComputerName = $S.Name
                            Property     = '*'
                            ErrorAction  = 'Stop'
                        }                
                        $Details = Get-CimInstance @CimParams

                        Foreach ($P in $Printers) {
                            Foreach($D in $Details) {
                                if ($P.Name -eq $D.Name) {
                                    $Props = @{
                                        DriverVersion = $D.DriverVersion
                                        Collate       = $D.Collate
                                        Color         = $D.Color
                                        Copies        = $D.Copies
                                        Duplex        = $D.Duplex
                                        PaperSize     = $D.PaperSize
                                        Orientation   = $D.Orientation
                                        PrintQuality  = $D.PrintQuality
                                    }
                                    $P | Add-Member -NotePropertyMembers $Props -TypeName NoteProperty
                                    Break
                                }
                            }
                        }
                        [PSCustomObject]@{
                                ComputerName   = $S.Name
                                ComputerStatus = "Ok" 
                                RetrievalDate  = (Get-Date -Format "dd/MM/yyyy HH:mm")
                                PrinterDetails = $Printers
                       }
                    }
                }
            }
            Catch {
                if (Test-Connection $S.Name -Count 2 -EA Ignore) {
                    [PSCustomObject]@{
                        ComputerName   = $S.Name
                        ComputerStatus = "ERROR: $($Error[0].Exception.Message)" 
                        RetrievalDate  = (Get-Date -Format "dd/MM/yyyy HH:mm")
                        PrinterDetails = $null
                    }
                }
                else {
                    [PSCustomObject]@{
                        ComputerName   = $S.Name
                        ComputerStatus = 'Offline'
                        RetrievalDate  = (Get-Date -Format "dd/MM/yyyy HH:mm")
                        PrinterDetails = $null
                    }
                }
            }
        }
    }
}


$Servers = 'SERVER1', 'SERVER2' | Get-ADComputer | Select-Object Name, Enabled

Get-PrintersInstalledHC $Servers

这可能意味着您可能需要在检索详细信息后进行一些额外的分析,但它会为您提供更加可预测的对象。 PrinterDetails属性现在应该是一个自定义对象数组,因此您可以ForEach覆盖它(如果它不是$null)并撤回您想要的位。