我们遇到了一些奇怪的问题。我们创建的函数工作正常,并在第一个对象具有所需的所有属性时输出所有属性。如果不是这种情况,它只会将自己限制在第一个对象的输出中。
我知道这听起来有点令人困惑,但这就是我的意思:
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
上失败。
答案 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
)并撤回您想要的位。