Docs / Windows Server / Set Up a Windows Print Server

Set Up a Windows Print Server

By Admin · Mar 15, 2026 · Updated Apr 24, 2026 · 254 views · 3 min read

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)         

Was this article helpful?