Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Working with Scripting.Dictionary and pritners

Status
Not open for further replies.

Keegans

Technical User
Nov 13, 2012
9
US
Hello everyone!

I found this FAQ and I am trying to implement part of it: ---
Set WSHNetwork = CreateObject("WScript.Network")

'Install only missing printers from predefined list
'Thanks go to DM4Ever for this section
'Create a dictionary to store our printer paths
Set objDictPrnts = CreateObject("Scripting.Dictionary")
objDictPrnts.CompareMode = vbTextCompare
objDictPrnts.Add "\\spidersparlor\HPLaserJet3", "\\spidersparlor\HPLaserJet3"
objDictPrnts.Add "\\spidersparlor\HPLaserJet4", "\\spidersparlor\HPLaserJet4"
objDictPrnts.Add "\\spidersparlor\Accounting", "\\spidersparlor\Accounting"
objDictPrnts.Add "\\spidersparlor\ColorPrinter", "\\spidersparlor\ColorPrinter"
objDictPrnts.Add "\\spidersparlor\tektronics", "\\spidersparlor\tektronics"

' loop through printer connections
Set WSHPrinters = WSHNetwork.EnumPrinterConnections
For LOOP_COUNTER = 0 To WSHPrinters.Count - 1 Step 2
PrinterPath = WSHPrinters.Item(LOOP_COUNTER +1)
' if the current path exist in our dictionary remove it
If objDictPrnts.Exists(PrinterPath) Then objDictPrnts.Remove PrinterPath
Next

' loop through the path's that were not found and add them
For Each PrinterPath In objDictPrnts.Keys
WSHNetwork.AddWindowsPrinterConnection PrinterPath
Next

--

What I have done is created the dictionary based on the groups the users are in. For example:

--
strArch = Right(wshShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%"), 2)
IF (strArch = 86) Then
strPrintServer = "\\32BitServer\"
strPrintArch = " 32"
End IF
IF (strArch = 64) Then
strPrintServer = "\\64BitServer\"
strPrintArch = " 64"
End IF

If (IsMember(objUser, "PRN_Room_146_Printer") = True) Then
objDictPrnts.Add strPrintServer & "CHS Room 146 Printer" & strPrintArch, strPrintServer & "CHS Room 146 Printer" & strPrintArch
End If

--

So far that all seems to work. I tested my functions by getting the objDictPrnts.Count and it returns the correct number.

The problem is that nothing seems to be working when going through this part
--
' loop through printer connections
Set WSHPrinters = WSHNetwork.EnumPrinterConnections
For LOOP_COUNTER = 0 To WSHPrinters.Count - 1 Step 2
PrinterPath = WSHPrinters.Item(LOOP_COUNTER +1)
' if the current path exist in our dictionary remove it
If objDictPrnts.Exists(PrinterPath) Then objDictPrnts.Remove PrinterPath
Next

' loop through the path's that were not found and add them
For Each PrinterPath In objDictPrnts.Keys
WSHNetwork.AddWindowsPrinterConnection PrinterPath
Next
--

I am using this on printers that are already on the computer and I get the same count for the array before and after the printers should be deleted from the array. Also, the printers never are mapped to the computers.

The clients are Win7.

I know we can use GP for this but we already have something like this in place, I just want to streamline it (and hopefully fix the issues we are having with the printers not mapping randomly.)

Any help would be appreciated.

Thank you,

Keegan
 
I tested my functions by getting the objDictPrnts.Count and it returns the correct number.

maybe so, but does it contain the correct information. I would recommend verifying the contents of your vars and objects

Code:
 Set WSHPrinters = WSHNetwork.EnumPrinterConnections
 For LOOP_COUNTER = 0 To WSHPrinters.Count - 1 Step 2
 PrinterPath = WSHPrinters.Item(LOOP_COUNTER +1)
 [red]msgbox PrinterPath[/red]
 ' if the current path exist in our dictionary remove it
 If objDictPrnts.Exists(PrinterPath) Then objDictPrnts.Remove PrinterPath
 Next
 
' loop through the path's that were not found and add them
For Each PrinterPath In objDictPrnts.Keys
    [red]msgbox PrinterPath[/red]
    WSHNetwork.AddWindowsPrinterConnection PrinterPath
Next

-Geates

 
msgbox PrinterPath

Does not show a message box at all.
 
To be perfectly honest, I have no idea. Its how they had it in the FAQ I mentioned.

Do you have another way of doing that command? It should take in the already mapped printers and then go through the mapped ones and delete them if they exist in the objDictPrnts.
 
What I was inferring is that WSHPrinters is nothing. If that's the case, WSHPrinters.count - 1 = -1. Therefore, the for loop evaluates to [tt]For LOOP_COUNTER = 0 To - 1 Step 2[/tt], which is impossible because your can't get to -1 from 0 by adding increments of 2 (step 2).

Put a msgbox after enumerating the printers. What does it say?

Code:
Set WSHPrinters = WSHNetwork.EnumPrinterConnections
msgbox WSHPrinters.count

Please post your entire script within [ignore]
Code:
<script goes here>
[/ignore] tags. The possible problem described above would depend on code that has not been posted. Without it, troubleshooting can be difficult.

-Geates

 
I shortened the code a bit here to make it fit. The omitted stuff is drive mapping

Code:
Option Explicit

On Error Resume Next

Dim objNetwork, objSysInfo, strUserDN
Dim objGroupList, objUser, objFSO
Dim strComputerDN, objComputer
'change made to correct users losing the H drive KS 10/24/2012
Dim wshShell, strUserName
Dim strArch 'Computer Architecture
Dim strPrintServer, strPrintArch 'Place holder for print server name and type (32 or 64)
Dim strDefaultPrinter, objDictPrnts, WSHPrinters

Set objNetwork = CreateObject("Wscript.Network")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objSysInfo = CreateObject("ADSystemInfo")
strUserDN = objSysInfo.userName
strComputerDN = objSysInfo.computerName
'change made to correct users losing the H drive KS 10/24/2012
Set wshShell = WScript.CreateObject( "WScript.Shell" )
strUserName = wshShell.ExpandEnvironmentStrings( "%USERNAME%" )

' Escape any forward slash characters, "/", with the backslash
' escape character. All other characters that should be escaped are.
strUserDN = Replace(strUserDN, "/", "\/")
strComputerDN = Replace(strComputerDN, "/", "\/")


' Bind to the user objects with the LDAP provider.
Set objUser = GetObject("LDAP://" & strUserDN)
Set objComputer = GetObject("LDAP://" & strComputerDN)

'Install only missing printers from predefined list
'Thanks go to DM4Ever for this section
'Create a dictionary to store our printer paths
'KJS 11/13/2012
Set objDictPrnts = CreateObject("Scripting.Dictionary")
objDictPrnts.CompareMode = vbTextCompare

'Get file system type
'Options are 64 and 86. Space needed at the beginning of the PrintArch 
strArch = Right(wshShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%"), 2)
IF (strArch = 86) Then
	strPrintServer = "\\32BitServer\"
	strPrintArch = " 32"
End IF 
IF (strArch = 64) Then
	strPrintServer = "\\64BitServer\"
	strPrintArch = " 64"
End IF 


If (IsMember(objComputer, "CHS-LMC-PCS") = True) Then
    	objDictPrnts.Add strPrintServer & "CHS LMC Copier" & strPrintArch, strPrintServer & "CHS LMC Copier" & strPrintArch
		objDictPrnts.Add strPrintServer & "CHS LMC HP B&W" & strPrintArch, strPrintServer & "CHS LMC HP B&W" & strPrintArch
		objDictPrnts.Add strPrintServer & "CHS LMC Color" & strPrintArch, strPrintServer & "CHS LMC Color" & strPrintArch
				
    	strDefaultPrinter = "CHS LMC Copier"
End If

If (IsMember(objUser, "PRN_CHS_Bus_Ed_B&W") = True) Then
	objDictPrnts.Add strPrintServer & "CHS Bus Ed B&W" & strPrintArch, strPrintServer & "CHS Bus Ed B&W" & strPrintArch
End If

' Actually Map the printers
' loop through printer connections
Set WSHPrinters = objNetwork.EnumPrinterConnections
For LOOP_COUNTER = 0 To WSHPrinters.Count - 1 Step 2
	PrinterPath = WSHPrinters.Item(LOOP_COUNTER +1)
	MsgBox PrinterPath
    ' if the current path exist in our dictionary remove it
    If objDictPrnts.Exists(PrinterPath) Then objDictPrnts.Remove PrinterPath
Next

MsgBox objDictPrnts.Count & " Printers to Be Installed After"
' loop through the path's that were not found and add them
For Each PrinterPath In objDictPrnts.Keys
	msgbox PrinterPath
    objNetwork.AddWindowsPrinterConnection PrinterPath
Next 

'Set network printer if its set
If Len(strDefaultPrinter) Then
	objNetwork.SetDefaultPrinter strPrintServer & strDefaultPrinter & strPrintArch
End If
 
Code:
Script: logon.vbs
Line: 176
Char: 6
Error: This key is already associated with an element of this collection
Code: 800A01C9
Source: Microsoft VBScript runtime error.

Code:
'Line 176
objDictPrnts.Add strPrintServer & "CHS LMC Copier" & strPrintArch, strPrintServer & "CHS LMC Copier" & strPrintArch
 
To avoid this, I am thinking I need to write a function for adding to the array that checks to see if the key is already taken. That way we can move beyond this error and onto others :)
 
Completely new to vbs. I know in php I could add a ! to make it the opposite and eliminate the Then with nothing to do there. I don't know if that can be done in vbs.

Code:
Function addToDict(ByVal strPrinterPath)
	If objDictPrnts.Exists(strPrinterPath) 
	Then 
	Else
		objDictPrnts.Add strPrinterPath, strPrinterPath
	End If
End Function
 
Code:
Function addToDict(ByVal strPrinterPath)
If Not objDictPrnts.Exists(strPrinterPath) Then
  objDictPrnts.Add strPrinterPath, strPrinterPath
End If
End Function

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
writing a function would be a work-around and likely acceptable in terms of your goal. However, there is a deeper issue at had. Why is the key already taken? The scripts logic is not correct if it's trying to add the same item twice. Is it even the same item or a different one with the same name?

A well written script (in any language) should not have the opportunity to produce an error.

-Geates

 
Well in this case it may.

This is being written for a school setting. If the teacher has requested that they have a specific printer anywhere they log in, and we want the computer to have the same printer by default (no matter who is sitting there) then we will have overlapping printers and we will get that error.

The function will then prevent the error from occurring.

I appreciate the thought, but in this case well written will have to include getting rid of this error.
 
Changes made

This was added at the end of the code
Code:
Function addToDict(ByVal strPrinterPath)
	If Not objDictPrnts.Exists(strPrinterPath) Then
		objDictPrnts.Add strPrinterPath, strPrinterPath 
	End If
End Function

All printer statements were changed to the following
[Code}
If (IsMember(objComputer, "CHS-LMC-PCS") = True) Then
addToDict(strPrintServer & "CHS LMC Copier" & strPrintArch)
addToDict(strPrintServer & "CHS LMC HP B&W" & strPrintArch)
addToDict(strPrintServer & "CHS LMC Color" & strPrintArch)

strDefaultPrinter = "CHS LMC Copier"
End If
[/code]

New error messages appeared about LOOP_COUNTER and PrinterPath not being defined.

Added the following:
Code:
Dim LOOP_COUNTER, PrinterPath
Just above the For loop

And now its working!!

Thank you very much!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top