Pages

Tuesday, March 29, 2011

Powershell for Printer Information from Windows 2008

While working on migrating are campus print server to Windows 2008 R2 64 bit I wrote some Powershell scripts I figured others may find useful. I have other scripts I'll post in the future on creating and working with printers but this post is primarily about getting data about the printers and ports.

The end result is are three excel files (CSV).
  1. Contains all the information about the printers on the server.
  2. Contains the Ports information and tries to ping the Host Address to see if the port is valid
  3. Joins the data so that you can see the printer and its port information all together.
All the data is gathered via WMI so you'll need administrative access to the server your running it against. I used PowerGUI to write and test this and have been quite happy with the outcome. Considering our server has 500 printers on it takes about 5 minutes to run but lower numbers of printers run much faster.

The fact that the scripts pings all the ports and reports their status is a feature I should of written a long time ago.


Command Line Output


Picutre of the resulting Files

Script

#Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Confirm $true
Clear 
#$ComputerName = "printserv1"
$ComputerName = Read-Host "Enter the print server name."

[bool] $QueryData = $true
[bool] $OutputFiles = $true

function Ping()
{
 param ([string] $ComputerName)
 [bool] $Pingable = $false
  
 try{
  $ping = new-object System.Net.NetworkInformation.Ping
  $Reply = $ping.send($ComputerName, 100)
  if ($Reply.status –eq “Success”) 
  {
   $Pingable = $true
  }
 } 
 catch
 {
  return "Error Resloving $ComputerName" 
 }
 
 if ($Pingable) 
 {
  return “Online”
 }
 else 
 {
  return "Offline"
 }
}
Function Get-Printers( )
{
 param ([string] $ComputerName  = ".") #sets "." as the default param if none is supplied

 
 Write-Host "Connecting to $ComputerName by WMI to gather printer information."
 Write-Host "Warning this may take a few minutes depending how many printers there are." -ForegroundColor Red
 
 $colItems = get-wmiobject -class "Win32_Printer" -namespace "root\CIMV2" -computername $ComputerName
 $count = $colItems.Count
 $pos = 0
 Write-Host "Found $count printers. Getting details on each now."
 $Printers = @()

 foreach ($objItem in $colItems) 
 {
  write-progress -activity "Getting Information on each printer." -status "% Complete" -percentcomplete (($pos++/$count)*100);
    
  #$list = "" | select "AvgPagesPerMinute", "Caption", "Comment", "Default", "DriverName" ,"InstallDate", "JobCountSinceLastReset", "Local", "Location" ,"Name", `
  #"Network", "PortName", "PrinterStatus", "PrintJobDataType", "PrintProcessor", "Shared", "ShareName", "Status", "StatusInfo", "SystemName" , "WorkOffline"
  
  #creating a new object called $PrinterInfo 
     $PrinterInfo = New-Object psobject  
   
     #write-host "Attributes: " $objItem.Attributes
     #write-host "Availability: " $objItem.Availability
     #write-host "Available Job Sheets: " $objItem.AvailableJobSheets
     $PrinterInfo | Add-Member NoteProperty NameAvgPagesPerMinute $objItem.AveragePagesPerMinute 
     #write-host "Capabilities: " $objItem.Capabilities
     #write-host "Capability Descriptions: " $objItem.CapabilityDescriptions
     $PrinterInfo | Add-Member NoteProperty Caption $objItem.Caption
     #write-host "Character Sets Supported: " $objItem.CharSetsSupported
     $PrinterInfo | Add-Member NoteProperty Comment  $objItem.Comment
     #write-host "Configuration Manager Error Code: " $objItem.ConfigManagerErrorCode
     #write-host "Configuration Manager User Configuration: " $objItem.ConfigManagerUserConfig
     #write-host "Creation Class Name: " $objItem.CreationClassName
     #write-host "Current Capabilities: " $objItem.CurrentCapabilities
     #write-host "Current Character Set: " $objItem.CurrentCharSet
     #write-host "Current Language: " $objItem.CurrentLanguage
     #write-host "Current MIME Type: " $objItem.CurrentMimeType
     #write-host "Current Natural Language: " $objItem.CurrentNaturalLanguage
     #write-host "Current Paper Type: " $objItem.CurrentPaperType
     $PrinterInfo | Add-Member NoteProperty "Default"  $objItem.Default
     #write-host "Default Capabilities: " $objItem.DefaultCapabilities
     #write-host "Default Copies: " $objItem.DefaultCopies
     #write-host "Default Language: " $objItem.DefaultLanguage
     #write-host "Default MIME Type: " $objItem.DefaultMimeType
     #write-host "Default Number Up: " $objItem.DefaultNumberUp
     #write-host "Default Paper Type: " $objItem.DefaultPaperType
     #write-host "Default Priority: " $objItem.DefaultPriority
     #write-host "Description: " $objItem.Description
     #write-host "Detected Error State: " $objItem.DetectedErrorState
     #write-host "Device ID: " $objItem.DeviceID
     #write-host "Direct: " $objItem.Direct
     #write-host "Do Complete First: " $objItem.DoCompleteFirst
     $PrinterInfo | Add-Member NoteProperty "DriverName" $objItem.DriverName
     #write-host "Enable BIDI: " $objItem.EnableBIDI
     #write-host "Enable Device Query Print: " $objItem.EnableDevQueryPrint
     #write-host "Error Cleared: " $objItem.ErrorCleared
     #write-host "Error Description: " $objItem.ErrorDescription
     #write-host "Error Information: " $objItem.ErrorInformation
     #write-host "Extended Detected Error State: " $objItem.ExtendedDetectedErrorState
     #write-host "Extended Printer Status: " $objItem.ExtendedPrinterStatus
     #write-host "Hidden: " $objItem.Hidden
     #write-host "Horizontal Resolution: " $objItem.HorizontalResolution
     #$PrinterInfo | Add-Member NoteProperty "InstallDate" $objItem.InstallDate
     $PrinterInfo | Add-Member NoteProperty "JobCountSinceLastReset" $objItem.JobCountSinceLastReset
     #write-host "Keep Printed Jobs: " $objItem.KeepPrintedJobs
     #write-host "Languages Supported: " $objItem.LanguagesSupported
     #write-host "Last Error Code: " $objItem.LastErrorCode
     $PrinterInfo | Add-Member NoteProperty "Local" $objItem.Local
     $PrinterInfo | Add-Member NoteProperty "Location" $objItem.Location
     #write-host "Marking Technology: " $objItem.MarkingTechnology
     #write-host "Maximum Copies: " $objItem.MaxCopies
     #write-host "Maximum Number Up: " $objItem.MaxNumberUp
     #write-host "Maximum Size Supported: " $objItem.MaxSizeSupported
     #write-host "MIME Types Supported: " $objItem.MimeTypesSupported
     $PrinterInfo | Add-Member NoteProperty "Name" $objItem.Name
     #write-host "Natural Languages Supported: " $objItem.NaturalLanguagesSupported
     $PrinterInfo | Add-Member NoteProperty "Network" $objItem.Network
     #write-host "Paper Sizes Supported: " $objItem.PaperSizesSupported
     #write-host "Paper Types Available: " $objItem.PaperTypesAvailable
     #write-host "Parameters: " $objItem.Parameters
     #write-host "PNP Device ID: " $objItem.PNPDeviceID
     $PrinterInfo | Add-Member NoteProperty "PortName" $objItem.PortName
     #write-host "Power Management Capabilities: " $objItem.PowerManagementCapabilities
     #write-host "Power Management Supported: " $objItem.PowerManagementSupported
     #write-host "Printer Paper Names: " $objItem.PrinterPaperNames
     #write-host "Printer State: " $objItem.PrinterState
     $PrinterInfo | Add-Member NoteProperty "PrinterStatus" $objItem.PrinterStatus
     $PrinterInfo | Add-Member NoteProperty "PrintJobDataType" $objItem.PrintJobDataType
     $PrinterInfo | Add-Member NoteProperty "PrintProcessor" $objItem.PrintProcessor
     #write-host "Priority: " $objItem.Priority
     #write-host "Published: " $objItem.Published
     #write-host "Queued: " $objItem.Queued
     #write-host "Raw-Only: " $objItem.RawOnly
     #write-host "Separator File: " $objItem.SeparatorFile
     #write-host "Server Name: " $objItem.ServerName
     $PrinterInfo | Add-Member NoteProperty "Shared" $objItem.Shared
     $PrinterInfo | Add-Member NoteProperty "ShareName" $objItem.ShareName
     #write-host "Spool Enabled: " $objItem.SpoolEnabled
     #write-host "Start Time: " $objItem.StartTime
     $PrinterInfo | Add-Member NoteProperty "Status" $objItem.Status
     $PrinterInfo | Add-Member NoteProperty "StatusInfo" $objItem.StatusInfo
     #write-host "System Creation Class Name: " $objItem.SystemCreationClassName
     $PrinterInfo | Add-Member NoteProperty "SystemName" $objItem.SystemName
     #write-host "Time Of Last Reset: " $objItem.TimeOfLastReset
     #write-host "Until Time: " $objItem.UntilTime
     #write-host "Vertical Resolution: " $objItem.VerticalResolution
     $PrinterInfo | Add-Member NoteProperty "WorkOffline" $objItem.WorkOffline
     
  $Printers += $PrinterInfo
    
 }
 write-progress -activity "Getting Information on each Port." -status "% Complete:" -percentcomplete 100 -Completed;
 return $Printers
}

function Get-PortInfo ()
{
 param ([string] $ComputerName  = ".") #sets "." as the default param if none is supplied
 
  
 Write-Host "Connecting to $ComputerName by WMI to gather printer port information."
 Write-Host "Warning this may take a few minutes because its pinging each port." -ForegroundColor Red
 
 
 
 
 $colItems = get-wmiobject -class "Win32_TCPIPPrinterPort" -namespace "root\CIMV2" -computername $ComputerName
 $count = $colItems.Count
 $pos = 0
 Write-Host "Found $count printer ports. Getting details on each now."
 
 
 $Ports = @()
 
 foreach ($objItem in $colItems)
 {
  write-progress -activity "Getting Information on each Port." -status "% Complete:" -percentcomplete (($pos++/$count)*100);
  
  $PortInfo = New-Object psobject  
  $PortInfo | Add-Member NoteProperty "ByteCount" $objItem.ByteCount
  $PortInfo | Add-Member NoteProperty "Caption: " $objItem.Caption
  $PortInfo | Add-Member NoteProperty "CreationClassName" $objItem.CreationClassName
  $PortInfo | Add-Member NoteProperty "Description: " $objItem.Description
  $PortInfo | Add-Member NoteProperty "HostAddress" $objItem.HostAddress
  $PortInfo | Add-Member NoteProperty "InstallDate" $objItem.InstallDate
  $PortInfo | Add-Member NoteProperty "Name" $objItem.Name
  $PortInfo | Add-Member NoteProperty "PortNumber" $objItem.PortNumber
  $PortInfo | Add-Member NoteProperty "Protocol" $objItem.Protocol
  $PortInfo | Add-Member NoteProperty "Queue" $objItem.Queue
  $PortInfo | Add-Member NoteProperty "SNMPCommunity" $objItem.SNMPCommunity
  $PortInfo | Add-Member NoteProperty "SNMPDevIndex" $objItem.SNMPDevIndex
  $PortInfo | Add-Member NoteProperty "SNMPEnabled" $objItem.SNMPEnabled
  $PortInfo | Add-Member NoteProperty "Status" $objItem.Status
  $PortInfo | Add-Member NoteProperty "SystemCreationClassName" $objItem.SystemCreationClassName
  $PortInfo | Add-Member NoteProperty "SystemName" $objItem.SystemName
  $PortInfo | Add-Member NoteProperty "Type" $objItem.Type
  $PortInfo | Add-Member NoteProperty "Ping" (Ping -ComputerName $objItem.HostAddress)
  
  $Ports += $PortInfo
 }
 write-progress -activity "Getting Information on each Port." -status "% Complete:" -percentcomplete 100 -Completed;
 return $Ports
}
function Get-PritnersWithPort {
param ( [array] $Printers,
  [array] $Ports  )

 
 $PrinterWithPortInfo = @()
 Foreach($Printer in $Printers)
 {
  $Port = $Ports | where {$_.Name -like ($Printer.PortName) }
  if($Port -ne $null)
  {
   $properties = $Port | Get-Member -MemberType NoteProperty
   
   foreach ($member in $properties )
   {
    $PropName = $member.Name
    $PropValue = $Port | Get-Member -MemberType NoteProperty ($member.Name) 
    
    $PropValue = $PropValue.ToString().Split("=")[1]
    
    if($PropValue -match "null")
    { $PropValue = ""}
    
    $Printer | Add-Member NoteProperty ("Port_" + $Propname) $PropValue
   }
  }
  $PrinterWithPortInfo += $Printer
 }
 return $PrinterWithPortInfo
}

function Get-PortsWithPrinterAndOnline 
{
param ( [array] $Printers , 
  [array] $Ports  )
 
 $PortsWithPrinterAndOnline = @()
 Foreach($Printer in $Printers)
 {
   $Port = $Ports | where { $_.Name -like ($Printer.PortName) -and ( $_.Ping -like "Online") }
   $PortsWithPrinterAndOnline += $Port
 }
 
 return $PortsWithPrinterAndOnline
}




function CreatePrinterPort {
 param ( [string] $ComputerName  = ".", #sets "." as the default param if none is supplied
  [string] $PortName ,
  [string] $DNSName ,
  [int] $Protocol = 1,  #default of 1 for RAW
  [string]$Queue = $null,
  [string]$PortNumber =  "9100",
  [bool] $SNMPEnabled ,
  [string] $SNMPCommunity = $null)
 

 #$newPort = [wmiclass]"Win32_TcpIpPrinterPort"
 #$port = get-wmiobject -class "Win32_TCPIPPrinterPort" -namespace "root\CIMV2" -computername $ComputerName
 $newPort = ([WMICLASS]"\\$ComputerName\ROOT\cimv2:Win32_TCPIPPrinterPort").createInstance() 
 $newport.Name= $PortName
 $newport.HostAddress= $DNSName #sometimes IP Address
 $newport.Protocol= $Protocol 
 #Protocols possiable
 #1 = RAW, Printing directly to a device or print server.
 #2 = LPR, Legacy protocol, which is eventually replaced by RAW.
 
 if ($Protocol -eq 2 ) {
  $newport.Queue = $Queue 
 }
 
 
 $newPort.PortNumber = "9100"
 $newport.SNMPEnabled = $SNMPEnabled
 
 if( $SNMPCommunity -ne $null ) {
  $newport.SNMPCommunity = $SNMPCommunity
 }
 Write-Host "Creating Port $PortName" -foregroundcolor "darkgreen"
 [void] $newport.Put()
 
 
}
#################################################################################
#        MAIN           #
#################################################################################


#Formated File Names
$d = get-date
$FileTime = "" + $d.Year + "-" + $d.Month + "-" + $d.Day + "-" + $d.Hour + $d.Minute
$PortsFilename = [String]::Format( "{0}_Ports_{1}.csv", $ComputerName, $FileTime )
$PritnersFilename = [String]::Format( "{0}_Printers_{1}.csv", $ComputerName, $FileTime )
$PritnersWithPortFilename = [String]::Format( "{0}_PritnersWithPort_{1}.csv", $ComputerName, $FileTime )

if( $QueryData )
{
 #Gets all the information
 $Printers = Get-Printers -ComputerName $ComputerName
 $Ports = Get-PortInfo -ComputerName $ComputerName
 $PrinterWithPortInfo = Get-PritnersWithPort -Printers $Printers -Ports  $Ports
}

if($OutputFiles)
{
 #writing file to 
 [Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath 
 Write-Host ("Saving CSV Files at " + [Environment]::CurrentDirectory + " Named the following.")
 Write-Host $PortsFilename 
 Write-Host $PritnersFilename
 Write-Host $PritnersWithPortFilename

 $Printers | Sort-Object "Name" | Export-Csv $PritnersFilename
 $Ports | Sort-Object "Name" | Export-Csv $PortsFilename
 $PrinterWithPortInfo | Sort-Object "Name" | Export-Csv $PritnersWithPortFilename
 

 #removes the top line as it just has #TYPE System.Management.Automation.PSCustomObject in it.
 get-content $PritnersFilename |  select -Skip 1 |  set-content "$PritnersFilename-temp"
 move  "$PritnersFilename-temp" $PritnersFilename -Force

 get-content $PortsFilename |  select -Skip 1 |  set-content "$PortsFilename-temp"
 move  "$PortsFilename-temp" $PortsFilename -Force
 
 get-content $PritnersWithPortFilename |  select -Skip 1 |  set-content "$PritnersWithPortFilename-temp"
 move  "$PritnersWithPortFilename-temp" $PritnersWithPortFilename -Force
 
}

4 comments:

  1. This looks like just the thing to clean up our mare's nest of a network printing environment (2 MS print servers hosting 2000+ printers). Unfortunately, when I run it on either of my print servers I get an 'out of memory' error on line 45 and an 'attempted to divide by zero' error on line 53. I end up with a large list of ports but the "PritnersWithPort" [sic] file is empty.

    I figured it might be a problem with my WMI setup so I ran the diagnostic on it. No help.

    Thoughts?

    Thanks

    ReplyDelete
  2. PowerShell is powerful but for me it adds a complexity that sometimes stops one seeing the tree because of the forest. For basic Print information on a Windows 2008, the good old tried and test “net view \\printserver >c:\printers.txt” does it for. Nonetheless I am glad there are sites like this one. Thanks Chris

    ReplyDelete
  3. This is a great script! I am by no means a script person... so I thought I would ask.... would there be any way to have this do an nslookup on the ip address and add that information in a column to the right of host address? That would be most beneficial indeed.

    Thanks for the hard work!
    Daniel

    ReplyDelete
  4. That's for sharing this awesome script. I really appreciate the skills and the information provided from the script. Thanks so much!

    ReplyDelete

Please leave a comment; someone, anyone!