A Windows Print Server centralizes printer management across your network, making it easy to deploy printers to users via Group Policy, monitor print queues, and manage drivers from a single location. This guide covers setting up a production print server on your Windows Server VPS.
Install Print Server Role
# Install Print and Document Services
Install-WindowsFeature -Name Print-Server -IncludeManagementTools
Install-WindowsFeature -Name Print-Internet -IncludeManagementTools # Internet Printing
# Verify
Get-WindowsFeature Print-*
Add Printers and Drivers
# Add a printer driver
Add-PrinterDriver -Name "HP Universal Printing PCL 6" `
-InfPath "C:\Drivers\HP\hpcu270u.inf"
# Add a TCP/IP printer port
Add-PrinterPort -Name "TCP_10.0.0.200" `
-PrinterHostAddress "10.0.0.200" `
-PortNumber 9100
# Add a printer
Add-Printer -Name "Marketing-HP-Color" `
-DriverName "HP Universal Printing PCL 6" `
-PortName "TCP_10.0.0.200" `
-Shared `
-ShareName "Marketing-Color" `
-Location "Building A, 2nd Floor" `
-Comment "HP Color LaserJet - Marketing Department" `
-Published
# Set printer defaults
Set-PrintConfiguration -PrinterName "Marketing-HP-Color" `
-DuplexingMode TwoSidedLongEdge `
-Color $true `
-PaperSize A4
# List all printers
Get-Printer | Format-Table Name, DriverName, PortName, Shared, Published
Deploy Printers via Group Policy
# Deploy printers to users/computers via GPO
# 1. Open Group Policy Management
# 2. Edit the desired GPO
# 3. Navigate to:
# User Config > Preferences > Control Panel Settings > Printers
# OR
# Computer Config > Preferences > Control Panel Settings > Printers
# PowerShell approach — create a logon script
$deployScript = @'
# Deploy-Printers.ps1
$printerServer = "\\printserver.corp.example.com"
$departmentPrinters = @{
"Marketing" = "$printerServer\Marketing-Color"
"Finance" = "$printerServer\Finance-BW"
"Engineering" = "$printerServer\Eng-Plotter"
}
# Get user department from AD
$user = [ADSI]"LDAP://$(([ADSISEARCHER]"samAccountName=$env:USERNAME").FindOne().Path)"
$department = $user.department[0]
if ($departmentPrinters.ContainsKey($department)) {
$printerPath = $departmentPrinters[$department]
if (-not (Get-Printer -Name $printerPath -ErrorAction SilentlyContinue)) {
Add-Printer -ConnectionName $printerPath
Write-Host "Added printer: $printerPath"
}
}
# Set default printer based on location
$defaultPrinter = "$printerServer\Main-Lobby-Printer"
(New-Object -ComObject WScript.Network).SetDefaultPrinter($defaultPrinter)
'@
Set-Content "\\corp.example.com\SYSVOL\corp.example.com\scripts\Deploy-Printers.ps1" $deployScript
Monitor Print Queues
# View all print jobs
Get-PrintJob -PrinterName "Marketing-HP-Color" | Format-Table Id, JobStatus, UserName, DocumentName, Size
# View jobs across all printers
Get-Printer | ForEach-Object {
Get-PrintJob -PrinterName $_.Name -ErrorAction SilentlyContinue
} | Format-Table PrinterName, UserName, DocumentName, JobStatus, Size
# Cancel stuck print jobs
Get-PrintJob -PrinterName "Marketing-HP-Color" | Where-Object { $_.JobStatus -eq "Error" } | Remove-PrintJob
# Restart print spooler
Restart-Service Spooler
# Monitor print queue health
$printers = Get-Printer | Where-Object Shared -eq $true
foreach ($printer in $printers) {
$jobs = Get-PrintJob -PrinterName $printer.Name -ErrorAction SilentlyContinue
$errorJobs = ($jobs | Where-Object { $_.JobStatus -match "Error" }).Count
[PSCustomObject]@{
Printer = $printer.Name
Status = $printer.PrinterStatus
QueuedJobs = $jobs.Count
ErrorJobs = $errorJobs
}
} | Format-Table
Print Logging and Auditing
# Enable print auditing
wevtutil sl Microsoft-Windows-PrintService/Operational /e:true
# View print history
Get-WinEvent -LogName "Microsoft-Windows-PrintService/Operational" -MaxEvents 50 | `
Where-Object Id -eq 307 | `
Select-Object TimeCreated, @{N="User";E={$_.Properties[2].Value}}, `
@{N="Document";E={$_.Properties[1].Value}}, `
@{N="Printer";E={$_.Properties[0].Value}}, `
@{N="Pages";E={$_.Properties[7].Value}} | Format-Table
# Print usage report
$startDate = (Get-Date).AddDays(-30)
$printEvents = Get-WinEvent -LogName "Microsoft-Windows-PrintService/Operational" `
-FilterXPath "*[System[EventID=307 and TimeCreated[timediff(@SystemTime)