PowerShell 对象检索所有对象属性
PowerShell Objects retrieving all 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
上失败而其他服务器成功时,它只输出 ComputerName
、ComputerStatus
和 RetrievalDate
。像这样:
$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
.
出现故障
答案是将打印机的详细信息作为您正在创建的对象的单独 属性。您的基本对象应如下所示:
ComputerName
ComputerStatus
RetrievalDate
PrinterDetails
您已经拥有前三个属性,而您目前正在做的是使该对象包含每台打印机的大量其他属性(如果计算机可访问)。
您需要做的是将大量属性放入其自己的对象并将其附加到第四个 属性。然后你可以遍历输出并做一些事情 if PrinterDetails
is not null.
我不完全明白你的 ForEach
循环中发生了什么 $P
和 $D
看起来你正在丰富 returns 来自的信息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
)并拉回您想要的位。
我们遇到了一些奇怪的问题。我们创建的函数工作正常,并在第一个对象具有所需的所有属性时输出所有属性。如果不是这种情况,它只限于第一个对象的输出。
我知道这听起来有点令人困惑,但这就是我的意思:
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
上失败而其他服务器成功时,它只输出 ComputerName
、ComputerStatus
和 RetrievalDate
。像这样:
$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
.
答案是将打印机的详细信息作为您正在创建的对象的单独 属性。您的基本对象应如下所示:
ComputerName
ComputerStatus
RetrievalDate
PrinterDetails
您已经拥有前三个属性,而您目前正在做的是使该对象包含每台打印机的大量其他属性(如果计算机可访问)。
您需要做的是将大量属性放入其自己的对象并将其附加到第四个 属性。然后你可以遍历输出并做一些事情 if PrinterDetails
is not null.
我不完全明白你的 ForEach
循环中发生了什么 $P
和 $D
看起来你正在丰富 returns 来自的信息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
)并拉回您想要的位。