Public/healthcheck/Get-PrintServerHealth.ps1
|
#Requires -Version 5.1 function Get-PrintServerHealth { <# .SYNOPSIS Retrieves print server health information from local or remote computers .DESCRIPTION Collects Spooler service status, printer counts by state, pending and errored print jobs, and port counts from one or more print servers. Each server produces a single typed object with an OverallHealth summary computed from the collected metrics. .PARAMETER ComputerName One or more computer names to query. Defaults to the local machine. Accepts pipeline input by value and by property name. .PARAMETER Credential Optional PSCredential for authenticating to remote computers. Not used for local queries. .EXAMPLE Get-PrintServerHealth Retrieves print server health for the local computer. .EXAMPLE Get-PrintServerHealth -ComputerName 'PRINT01' Retrieves print server health from a single remote server. .EXAMPLE 'PRINT01', 'PRINT02' | Get-PrintServerHealth -Credential (Get-Credential) Retrieves print server health from multiple remote servers via pipeline. .OUTPUTS PSWinOps.PrintServerHealth Returns one object per server with service status, printer counts, job counts, port count, and an OverallHealth assessment. .NOTES Author: Franck SALLET Version: 1.0.0 Last Modified: 2026-03-26 Requires: PowerShell 5.1+ / Windows only Requires: PrintManagement module on target servers .LINK https://github.com/k9fr4n/PSWinOps .LINK https://learn.microsoft.com/en-us/powershell/module/printmanagement/ #> [CmdletBinding()] [OutputType('PSWinOps.PrintServerHealth')] param( [Parameter(Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [Alias('CN', 'Name', 'DNSHostName')] [string[]]$ComputerName = $env:COMPUTERNAME, [Parameter(Mandatory = $false)] [ValidateNotNull()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) begin { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Starting" $localNames = @($env:COMPUTERNAME, 'localhost', '.') $scriptBlock = { $serviceStatus = 'NotFound' $moduleAvailable = $false $totalPrinters = 0 $printersOnline = 0 $printersInError = 0 $printersOffline = 0 $totalPrintJobs = 0 $erroredPrintJobs = 0 $totalPorts = 0 try { $svc = Get-Service -Name 'Spooler' -ErrorAction Stop $serviceStatus = $svc.Status.ToString() } catch { $serviceStatus = 'NotFound' } $modCheck = Get-Module -Name 'PrintManagement' -ListAvailable -ErrorAction SilentlyContinue if ($modCheck) { $moduleAvailable = $true } if ($moduleAvailable -and $serviceStatus -eq 'Running') { $printerList = @(Get-Printer -ErrorAction SilentlyContinue) $totalPrinters = $printerList.Count foreach ($p in $printerList) { switch ($p.PrinterStatus) { 'Normal' { $printersOnline++ } 'Error' { $printersInError++ } 'Degraded' { $printersInError++ } 'Warning' { $printersInError++ } 'Offline' { $printersOffline++ } } } $jobList = @(Get-PrintJob -PrinterName '*' -ErrorAction SilentlyContinue) $totalPrintJobs = $jobList.Count foreach ($j in $jobList) { if ($j.JobStatus -match 'Error') { $erroredPrintJobs++ } } $totalPorts = @(Get-PrinterPort -ErrorAction SilentlyContinue).Count } @{ ServiceStatus = $serviceStatus ModuleAvailable = $moduleAvailable TotalPrinters = $totalPrinters PrintersOnline = $printersOnline PrintersInError = $printersInError PrintersOffline = $printersOffline TotalPrintJobs = $totalPrintJobs ErroredPrintJobs = $erroredPrintJobs TotalPorts = $totalPorts } } } process { foreach ($machine in $ComputerName) { $displayName = $machine.ToUpper() Write-Verbose -Message "[$($MyInvocation.MyCommand)] Querying '${machine}'" try { $isLocal = $localNames -contains $machine if ($isLocal) { $data = & $scriptBlock } else { $invokeParams = @{ ComputerName = $machine ScriptBlock = $scriptBlock ErrorAction = 'Stop' } if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) { $invokeParams['Credential'] = $Credential } $data = Invoke-Command @invokeParams } if (-not $data.ModuleAvailable) { $healthStatus = 'RoleUnavailable' } elseif ($data.ServiceStatus -ne 'Running' -or $data.PrintersInError -gt 0) { $healthStatus = 'Critical' } elseif ($data.PrintersOffline -gt 0 -or $data.ErroredPrintJobs -gt 0) { $healthStatus = 'Degraded' } else { $healthStatus = 'Healthy' } [PSCustomObject]@{ PSTypeName = 'PSWinOps.PrintServerHealth' ComputerName = $displayName ServiceName = 'Spooler' ServiceStatus = $data.ServiceStatus TotalPrinters = [int]$data.TotalPrinters PrintersOnline = [int]$data.PrintersOnline PrintersInError = [int]$data.PrintersInError PrintersOffline = [int]$data.PrintersOffline TotalPrintJobs = [int]$data.TotalPrintJobs ErroredPrintJobs = [int]$data.ErroredPrintJobs TotalPorts = [int]$data.TotalPorts OverallHealth = $healthStatus Timestamp = Get-Date -Format 'o' } } catch { Write-Error -Message "[$($MyInvocation.MyCommand)] Failed on '${machine}': $_" continue } } } end { Write-Verbose -Message "[$($MyInvocation.MyCommand)] Completed" } } |