The ramblings of an old IT Pro travelling the digital byways.

Sunday, October 26, 2008

More Fun with Windows Printers

Okay, so I suck at posting on a regular basis. I'm busy. Sorry.

Anyway...

If you follow this blog at all, you've probably reached the conclusion that I hate printers and print servers. You're partially right. I hate them because they're a pain in the butt, but I also enjoy them because they give me an opportunity to still do some technical stuff. Remember, I'm a manager now. I'm not supposed to be technical.

Previously I posted some code I adapted to monitor and generate statistics from my company's Windows print servers. Now I've worked on a script that runs with user rights to unmap and remap printers, correcting printer names and forcing the download of new drivers for each printer from the server. This is still a work in progress, but it works pretty darned well, even if I do say so myself. I was never very happy with anything I found on the Net, so this is my stab at this functionality. Please, feel free to give me advice for improvements, but also feel free to use this code at your own risk. I make no warranty of any of this code.


'****************************************************
' Script by Brian E. Tower
' October 2008
'
' This script enumerates printers, determines which printers are
' mapped to specific print servers, makes a list of these printers
' corrects the server they are mapped to, deletes the mappings, deletes the drivers,
' remaps the printers with correct server names and resets the default printer.
'****************************************************

CheckRunner 'makes sure your running with cscript, not wscript

Dim arrMappedPrinters()
Dim arrNewMappings()
intSize = 0
Dim i, strCurrentDefaultPrinter, strRoot, strDelCmd, WshNetwork, strPrtr, strBits

On Error Resume Next

strBits = GetOS()

If strBits = 0 Then
WScript.Echo
WScript.Echo "You are running a 32 bit OS. Proceeding..."
WScript.Echo

'find default printer currently set and set a variable equal to it and change to the right print server
strCurrentDefaultPrinter = ChgPrntSrv(GetDefaultPrinter)

'find the system root, save for later
Set objShell = WScript.CreateObject( "WScript.Shell" )
strRoot = objShell.ExpandEnvironmentStrings("%SYSTEMROOT%")
'this is the executable to delete all unused print drivers
strDelCmd = strRoot & "\system32\cscript.exe " & strRoot & "\system32\prndrvr.vbs -x"

Set WshNetwork = WScript.CreateObject("WScript.Network")
Set objPrinters = WshNetwork.EnumPrinterConnections

WScript.Echo "Cataloging printer mappings:"
WScript.Echo
For i = 0 to objPrinters.Count - 1 Step 2
strPrtr = lcase(objPrinters.Item(i+1))
If InStr(1, strPrtr, "\\n1") <> 0 Then
'push unc into array
ReDim Preserve arrMappedPrinters(intSize)
ReDim Preserve arrNewMappings(intSize)
arrMappedPrinters(intSize) = strPrtr
'change server names and put in newprinter array
arrNewMappings(intSize) = ChgPrntSrv(arrMappedPrinters(intSize))
intSize = intSize +1
ElseIf InStr(1, strPrtr, "\\ac") <> 0 Then
'push unc into array
ReDim Preserve arrMappedPrinters(intSize)
ReDim Preserve arrNewMappings(intSize)
arrMappedPrinters(intSize) = strPrtr
'change server names and put in newprinter array
arrNewMappings(intSize) = ChgPrntSrv(arrMappedPrinters(intSize))
intSize = intSize +1
End If
Next

' remove printers
WScript.Echo "Deleting current mappings:"
For each strPrinterPath in arrMappedPrinters
WScript.Echo "Deleting " & strPrinterPath
WshNetwork.RemovePrinterConnection strPrinterPath, true, true
Next

' delete drivers
WScript.Echo
WScript.Echo "Deleting unused print drivers:"
Set oExec = objShell.Exec(strDelCmd)

' remap printers
WScript.Echo
WScript.Echo "Remapping printers:"
For Each strPrinterAdd in arrNewMappings
WScript.Echo "Mapping " & strPrinterAdd
WshNetwork.AddWindowsPrinterConnection strPrinterAdd
If Err <> 0 Then
WScript.Echo "Error mapping " & strPrinterAdd & ". You will need to map this printer manually."
DisplayErrorInfo
End If
'WScript.Sleep 1000
Next

'set default printer
WScript.Echo
WScript.Echo "Setting Default Printer:"
If Not strCurrentDefaultPrinter = "" then
WScript.Echo "Setting default printer to " & strCurrentDefaultPrinter
WshNetwork.SetDefaultPrinter strCurrentDefaultPrinter
Else
WScript.Echo "No default printer defined"
End If

Else
WScript.Echo
WScript.Echo
WScript.Echo "64 bit OS detected. This utility does not run on 64 bit OS"
WScript.Echo
WScript.Echo
End If


'****************************************************
' Functions and Notes below this point
'****************************************************
Function GetDefaultPrinter() 'this function finds the default printer setting for the current user
Set objShell = CreateObject("WScript.Shell")
strRegVal = "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device"
strDefault = ""
On Error Resume Next
strDefault = objShell.RegRead(strRegVal)
strDefault = Left(strDefault ,InStr(strDefault, ",") - 1)
On Error Goto 0
GetDefaultPrinter = strDefault
End Function


Function ChgPrntSrv(strServer) 'this function converts old print server names to new print server names
If InStr(1, strServer, "\\n1ps01") <> 0 Then
ChgPrntSrv = Replace(strServer, "n1ps01", "n1print01")
ElseIf InStr(1, strServer, "\\n1ps02") <> 0 Then
ChgPrntSrv = Replace(strServer, "n1ps02", "n1print01")
ElseIf InStr(1, strServer, "\\n1ps03") <> 0 Then
ChgPrntSrv = Replace(strServer, "n1ps03", "n1print02")
ElseIf InStr(1, strServer, "\\n1ps04") <> 0 Then
ChgPrntSrv = Replace(strServer, "n1ps04", "n1print02")
ElseIf InStr(1, strServer, "\\n1prntsrv01") <> 0 Then
ChgPrntSrv = Replace(strServer, "n1prntsrv01", "n1print01")
ElseIf InStr(1, strServer, "\\n1prntsrv02") <> 0 Then
ChgPrntSrv = Replace(strServer, "n1prntsrv02", "n1print02")
ElseIf InStr(1, strServer, "\\acprnt01") <> 0 Then
ChgPrntSrv = Replace(strServer, "acprnt01", "acprint02")
ElseIf InStr(1, strServer, "\\acprnt02") <> 0 Then
ChgPrntSrv = Replace(strServer, "acprnt02", "acprint02")
ElseIf InStr(1, strServer, "\\acps02") <> 0 Then
ChgPrntSrv = Replace(strServer, "acps02", "acprint02")
ElseIf InStr(1, strServer, "\\acprnt03") <> 0 Then
ChgPrntSrv = Replace(strServer, "acprnt03", "acprint01")
ElseIf InStr(1, strServer, "\\acprnt04") <> 0 Then
ChgPrntSrv = Replace(strServer, "acprnt04", "acprint01")
ElseIf InStr(1, strServer, "\\acps01") <> 0 Then
ChgPrntSrv = Replace(strServer, "acps01", "acprint01")
Else
ChgPrntSrv = strServer
End If
End Function

Function GetOS() 'this function determines if the OS is 64 or 32 bit
Dim oWMI
Dim oOS, xOS
Dim oRX_Bit
Dim b64 'Boolean value. If true, it is 64Bit, else it's 32Bit.

Set oWMI = GetObject("winmgmts:")
Set oRX_Bit = New RegExp
oRX_Bit.Pattern = "x64"
oRX_Bit.IgnoreCase = True

Set oOS = oWMI.ExecQuery("SELECT * FROM Win32_OperatingSystem")
For Each xOS In oOS
If oRX_Bit.Test(xOS.Name) Then
b64 = True
Else
b64 = False
End If
Next
GetOS = b64
End Function

Sub DisplayErrorInfo
WScript.Echo "Error: : " & Err
WScript.Echo "Error (hex) : &H" & Hex(Err)
WScript.Echo "Source : " & Err.Source
WScript.Echo "Description : " & Err.Description
Err.Clear
End Sub

Sub CheckRunner
dim arrProgRun, intEnd, strExecute

arrProgRun = split(WScript.FullName, "\")
intEnd = Ubound(arrProgRun)
strExecute = arrProgRun(intEnd)

if not lcase(strExecute) = "cscript.exe" then
WScript.Echo "You must run this script with CScript. " & vbCrLf & "Please read the instructions!!!" & vbCrLf & vbCrLf & "Bet you clicked an icon."
WScript.Quit (1)
end if
End Sub

No comments:

About Me

My photo
A living, breathing contradiction.