Hi all,
although I have been playing around with Powershell for a while now, I never really got into it any deeper. After attending some inspiring sessions at Techmentor in Orlando last week (thanks Don!), I jumped on the first chance to create a script. The script is working and does exactly what I need it to do, but I’d be interested in getting some feedback if there is a better way to do it.
Here was the challenge:
We have around 40 print servers in AD that host various print queues. We try to follow some standards, but unfortunately, not all the admins adhere to them. I wanted to create a script that queries all print servers and identifies any non-standard printer ports. Our standard is that each print queues is associated with one printer port on its print server. The printer ports are supposed to be configured to have the same name as the printer. We require FQDNs and not IP address. So for printer1 on printserver1.domain.com, we should also have an associated printerport that is labeled as printer1.domain.com and its address is also printer1.domain.com.
Here is the code:
Function Get-NonStandardPrinterPorts { [CmdletBinding()] param( [Parameter(Mandatory=$True)] [string]$ComputerName ) $nonstdports=@() try { # Get all printer ports of printserver $computername $ports=Get-WMIObject -Class Win32_TcpIpPrinterPort -ComputerName $ComputerName -ErrorAction stop | Select Name,HostAddress # enumerate all ports and check if name or hostaddress are not following standard naming convention of printer.henkelgroup.net # if printer port does not follow standard, add to array $nonstdports foreach ($port in $ports) { if (($port.Name).ToLower() -notmatch "^\w+\.domain\.com" -or ($port.HostAddress).ToLower() -notmatch "^\w+\.domain\.com" ) { $properties=@{'PortName'=$port.Name;'PortAddress'=$port.HostAddress} $object=New-Object -TypeName PSObject -Property $properties $nonstdports+=$object } # end of if } # end of foreach } # end of try Catch { # in case of error, throw exception message Write-Error $_.Exception.Message } # end of catch # return object Write-Output $nonstdports } # end of function Function Get-PrinterPortAssignment { [CmdletBinding()] param ( [Parameter(mandatory=$True)] [array]$PortName, [Parameter(mandatory=$True)] [array]$PrinterName, [Parameter(mandatory=$True)] [string]$ComputerName ) $colPrinters=@() # enumerate all printer ports that were passed along in object with function call foreach ($port in $PortName) { $done=$false #enumerate all printers that were passed along in object with function call foreach ($printer in $PrinterName) { #compare if printer port and printer name match up, if they do add them to object if ($printer.PortName -eq $port.PortName) { $properties=@{'ComputerName'=$ComputerName; 'PortName'=$port.PortName; 'PortAddress'=$port.PortAddress; 'Printer'=$printer.name } $printq=New-Object -TypeName PSObject -Property $properties $colPrinters += $printq $done=$true continue } # end of if } # end of foreach # if no matching printer was found for a printer port, add printer port to array, but mark printer as "n/a" if (!($done)) { $properties=@{'ComputerName'=$ComputerName; 'PortName'=$port.PortName; 'PortAddress'=$port.PortAddress; 'Printer'='n/a' } $printq=New-Object -TypeName PSObject -Property $properties $colPrinters += $printq } # end of if } # end of foreach # return object Write-Output $colPrinters } # grab list of printservers from AD $servers=Get-ADComputer -filter "name -like '*printserver*'" | Select name $endresult=@() # enumerate list of printservers foreach ($computername in $servers.name) { $printers=@() # Get all non-standard printer ports from printserver $computername $nonstdports=Get-NonStandardPrinterPorts -ComputerName $computername # if non-standard printer ports were found, get a lost of all printers on server $computername if ($nonstdports) { $printers=Get-Printer -ComputerName $computername -ErrorAction Stop } # end of if # if printers were found on printserver $computername, get matching printer-printerport pairs if ($printers) { $result=Get-PrinterPortAssignment -PortName $nonstdports -PrinterName $printers -ComputerName $computername $endresult+=$result } # end of if } # end of foreach # format for output on console $endresult | Select ComputerName,Printer,PortName,PortAddress | Sort-Object ComputerName | Ft -AutoSize
I appreciate any feedback or suggestions for improvement you can provide.
Thanks much!