Page 1 of 1 1
Topic Options
#198091 - 2010-03-18 02:41 AM expertise sought for tweaking print mapping
BReed Offline
Fresh Scripter

Registered: 2010-03-17
Posts: 10
Loc: nc
Hello all, I've got a situation where I was hoping I could get some expert advice on how to fix it and/or just make it better.
I've only just started with kix a few days ago so I'm still just trying to get my feet wet. We've been having printer mapping issues at my new job and looking into the script, it was a complete mess so I'm trying to rewrite it.

Here's a part of the print.kix I'm planning on using to unmap and then map printers with ini. After pouring over the forum, using an ini seems like a good solid method considering the original script was just tons of case statments and if ingroups.

 Code:
 
Function UnmapPrinters() 
Dim $bk,$conn 
 $bk="HKEY_CURRENT_USER\Printers\Connections" 
 Do
  $conn=DelKey($bk+"\"+EnumKey($bk,0))
 Until @error
EndFunction

? "Unmapping printers...."
UnmapPrinters
? "Errors:"
@SERROR
;DelPrinterConnection ("")
;@SERROR
? "Done..."

$ID = Left(@WKSTA, 4)
$PrinterList = Split(ReadProfileString('C:\printers.ini', $ID, 'Printers'), ';')
$DefPrinter = ReadProfileString('C:\printers.ini', $ID, 'Default')
For Each $Printer in $PrinterList
	AddPrinterConnection($Printer)
Next
SetDefaultPrinter($DefPrinter)



Another part of the original script, and the part where I'm having problems is below. Basically we just have to create a printer (and we have hundreds) and make a matching print-printername and a printd- printername AD group. That sets their printers and default that way. I like that a lot since we do have roaming users and lots of onesies we have to setup.

What I'd like to do is start with the script at the top to set a bunch of dept printers but also have the ability to use the print groups already established to cover the one-offs. The part that I can't wrap my head around is to eliminate the redundancy of remapping printers that will already be in the users groups (because lots of users are already members of several print groups) and that have already just been mapped by the ini. It might be fine the way it is if we just clean up the print groups now and there won't be too much remapping happening, but I'll leave that up to any experts to decide

 Code:
 
;set index to 0 for looping through groups
$LoopIndex = 0

;get first group name
$UsersGroups = ENUMGROUP($Index)

;loop
DO
;if group name is longer than nothing
	if Len($UsersGroups) > 0

		;if group name starts with print
		if lcase(substr($UsersGroups, 1, 14)) = "westcare\print"
			
			;if group is a printd group, add first
			if lcase(substr($UsersGroups, 1, 16)) = "westcare\printd-"
				
				;add printer and make sure it’s successful
				if addprinterconnection('\\wcps1\' + lcase(substr($UsersGroups, 17))) = 0

					;display success message
					? "Added printer: " + substr($UsersGroups, 17)
				else
					;display error message and text
					? "Error Adding Printer: " + substr($UsersGroups, 17)
					? "Error: " + @SERROR
				endif

				;set default printer to group name after add
				if setdefaultprinter('\\wcps1\' + substr($UsersGroups, 17)) = 0
	
					;display success message.	
					? "Set default printer to: " + substr($UsersGroups, 17)
				Else
					;display error message and text
					? "Error Setting Default Printer: " + substr($UsersGroups, 17)
					? "Error: " + @SERROR
				EndIf
			else	
				;add printer if just a print- group
				if addprinterconnection('\\wcps1\' + lcase(substr($UsersGroups, 16))) = 0

					;display success message
					? "Added printer: " + substr($UsersGroups, 16)
				else
					;display error message and text
					? "Error Adding Printer: " + substr($UsersGroups, 16)
					? "Error: " + @SERROR
				endif			
			endif
		EndIf
	EndIf
	
;increase the loop counter by 1
$LoopIndex = $LoopIndex + 1

;get next group name
$UsersGroups = ENUMGROUP($LoopIndex)

;loop until end of groups list
UNTIL Len($UsersGroups) = 0



Thanks for taking a look guys and I look forward to any and all advice. And thank you for a great forum. I've learned a lot just from reading here, and credits to anyone I borrowed bits or pieces from code to make it work for me.

BR

Top
#198094 - 2010-03-18 01:48 PM Re: expertise sought for tweaking print mapping [Re: BReed]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
Welcome to KORG!

You might want to look at the Kix login script on my web site, as it will do everything you're looking for with no additional coding. All resources are in an INI file for easy management.. you can use per-user INI files for extreme cases or testing (I have a personal INI where changes are made and tested before being placed in the common INI file). With just a few printer resource definitions and some lookup tables, you can map the desired printers from a list of hundreds. Mapping can be by user or computer goup, user or computer OU, subnet, AD Site, or user.

There are numerous options for setting printer defaults. We use a concept of "default eligibility" - you might define 5 resource records for printers, with the actual printers defined by a lookup by computer or user OU. One of those resources will be the default printer for all users unless it is overridden by another method. You can define a COMPUTER=PRINTER default relationship to set per-computer defaults, or even define a local environment variable to set a locally attached printer as the default.

Take a look at the Configuration Guide for information. The script is free to download and we provide both free and fee-based support.

FYI - it's in use at many sites around the world, including the US region of a large international travel company where printers are mapped at hundreds of retail locations and multiple corporate locations. Despite making hundreds of resource mapping decisions for drives, printers, messages, and secondary commands, our script completes in under 15 seconds even on the WAN links. (All DCs are at HQ, kix & script run from the central DC, so time includes loading kix and the script).

A couple of things about your code:
  • Kix is case-insensitive - the LCase functions are unnecessary and just add a layer of complexity.
  • The IF LEN($USERGROUPS) > 0 statement can be replaced with IF $USERGROUPS - if the length is zero, it evaluates to false, if it contains any text, it evaluates to true. This results in a tiny performance gain, but when you do it many times, the results can be noticable.
  • "?" is a shortcut for @CRLF, not a shortcut for a print statement like it is in BASIC. CRLF usually comes at the end of a line. For simple things, it won't matter, but as your scripts become more complex, starting each line with a CRLF will lead to formatting problems. Consider - CLS, then @CRLF "Hi!" - what line is the message on? Certainly NOT the first line!
  • Consider using the EnumINI UDF to enumerate your INI file, or even one of the INI2Array UDFs. This could speed processing as well.
  • Your call to UNMAPPRINTERS will work because Kix is forgiving. Calling a function should include the parens, as in UNMAPPRINTERS(). Other languages would likely throw an error without the parens. It also makes the code clearer to the reader.
  • SubStr($string, 1, 10) is the same as Left($String, 10) and probably faster to execute.
  • You get extra points for commenting your work!


Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#198096 - 2010-03-18 09:39 PM Re: expertise sought for tweaking print mapping [Re: Glenn Barnas]
BReed Offline
Fresh Scripter

Registered: 2010-03-17
Posts: 10
Loc: nc
Thanks Glen, I actually have looked at your script and it is very nice, however for our environment, I think I can make it all happen nice and clean with just a few small, well crafted scripts (hopefully!). Plus it's giving me a chance to learn kix, which honestly is the most important part of the project for me.
Thank you for the insight and suggestions on getting the script up to snuff. I'll definitely implement your suggestions.

Top
#198097 - 2010-03-19 03:14 PM Re: expertise sought for tweaking print mapping [Re: BReed]
Bryce Offline
KiX Supporter
*****

Registered: 2000-02-29
Posts: 3167
Loc: Houston TX
an idea to prevent the actual effort of remapping an existing printer, use the same logic that you have to unmap the printers, to check if the printer is already mapped.

it will take a few extra lines of code, but if it prevents the time delay of the system trying to map an already existing printer, it should do the trick.

Top
#198100 - 2010-03-19 04:14 PM Re: expertise sought for tweaking print mapping [Re: Bryce]
Mart Moderator Offline
KiX Supporter
*****

Registered: 2002-03-27
Posts: 4673
Loc: The Netherlands
The code below checks if the printer is installed and installs it if it is not installed. It also sets the printer as default if it is not default. It requires the PriMapState() UDF.

 Code:
$printer = "\\server\printer"
If Not PriMapState($printer)
	$rc = AddPrinterConnection($printer)
	$rc = SetDefaultPrinter($printer)
Else
	If PriMapState($printer) <> "2"
		$rc = SetDefaultPrinter($printer)
	EndIf
EndIf


Edited by Mart (2010-03-19 04:15 PM)
_________________________
Mart

- Chuck Norris once sold ebay to ebay on ebay.

Top
#198104 - 2010-03-19 04:54 PM Re: expertise sought for tweaking print mapping [Re: Bryce]
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
I've fiddled around with your code a bit and ended up with this (untested):
 Code:
Dim $sDOMAIN,$sSpooler,$sDone,$iDefaultDone
$sDOMAIN="westcare"
$sSpooler="\\wcps1\"
$sDone=@CRLF
$iDefaultDone=0

;set index to 0 for looping through groups
$iIndex = 0

;get first group name
$sGroup=EnumGroup($Index)
While Len($sGroup) AND @ERROR=0
	;if group name starts with print- or printd-
	If (InStr($sGroup,$sDOMAIN+"\print-")=1) OR (InStr($sGroup,$sDOMAIN+"\printd-")=1)
		$sPrinter=SubStr($sGroup,InStr($sGroup,"-")+1) ; Note, this won't work if you have "-" in the domain name
		If InStr($sDone,@CRLF+$sPrinter+@CRLF)
			; Printer has already been added - no point in doing it again.
		Else
			; Add printer and make sure it’s successful
			If AddPrinterConnection($sSpooler+$sPrinter)
				; Display error message and text
				"Error Adding Printer: "+$sPrinter+@CRLF
				"Error: "+@SERROR+@CRLF
			Else
				"Added printer: "+$sPrinter+@CRLF	; Display success message
				$sDone=$sDone+$sPrinter+@CRLF		; Record success
			EndIf
		EndIf
		; If printer has been added OK AND is default AND a default has not been set already...
		If InStr($sDone,@CRLF+$sPrinter+@CRLF) AND InStr($sGroup,$sDOMAIN+"\printd-")=1 AND $iDefaultDone=0
			If SetDefaultPrinter($s$sPrinter)
				; Display error message and text
				"Error Setting Default Printer: "+$sPrinter+@CRLF
				"Error: "+@SERROR+@CRLF
			Else
				"Set default to: "+$sPrinter+@CRLF	; Display success message.	
				$iDefaultDone=1
			EndIf
		EndIf
	EndIf
	$iIndex=$iIndex+1		 ;increase the loop counter by 1
	$sGroup=EnumGroup($iIndex)	 ;get next group name

; loop until end of groups list
Loop


So what's changed...
  • Constants like the domain and print server are abstracted to variables.
    This makes things easy to change and makes errors easier to trap and fix.
  • The code to add printers has been collapsed into one segment.
    You should never write the same code twice - if you cannot coded it inline once then wrap it up in a function and re-use it. This way if you want to make a change to the way that you map the printer or handle the errors you only need to change the function once.
  • Successful printer mappings are stored in the $sDone variable, so we don't try to add the same printer again. If you are adding printers elsewhere (such as via the INI file) then you should add them to this list on success. Alternatively you can use Mart's PriMapState() example.
  • Setting the default printer is only done once - you can't have more than one default. Again, if you might set the default elsewhere then set the $iDefaultDone flag when you do it.
  • Printer name pulled from group name and reused. I was running out of SubStr() tiles in my KiXtart Scrabble bag.
  • Buggy use of index variables sorted. You ARE using SetOption(Explicit,"ON") in your code, aren't you?

Top
#198107 - 2010-03-19 11:43 PM Re: expertise sought for tweaking print mapping [Re: Richard H.]
BReed Offline
Fresh Scripter

Registered: 2010-03-17
Posts: 10
Loc: nc
That's exactly why I posted here guys, excellent input. I'm really new to scripting (other than batch files)so it takes me a little longer to dissect and understand exactly what's happening where (and why often code I do isn't done the best way because of lack of experience). I'm going to dive into this over the weekend and see how it pans out. Again, thanks so much for the input everyone, and especially Richard - breaking that down gives me a better understanding of what should be happening as opposed to how it was happening.

Edited by BReed (2010-03-20 02:21 AM)

Top
#198108 - 2010-03-20 05:38 AM Re: expertise sought for tweaking print mapping [Re: Richard H.]
BReed Offline
Fresh Scripter

Registered: 2010-03-17
Posts: 10
Loc: nc
Hey Richard, so to prevent the redundency since I will be mapping printers from the ini first, how exactly would I tie the results into the $sDone variable if I'm starting with the code below?
 Code:
$ID = Left(@WKSTA, 4)
$PrinterList = Split(ReadProfileString('C:\printers.ini', $ID, 'Printers'), ';')
$DefPrinter = ReadProfileString('C:\printers.ini', $ID, 'Default')
For Each $Printer in $PrinterList
	AddPrinterConnection($Printer)
Next
SetDefaultPrinter($DefPrinter)

 


thanks mate, this site has been a lifesaver

Top
#198120 - 2010-03-22 10:33 AM Re: expertise sought for tweaking print mapping [Re: BReed]
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Here you go both the INI and group style additions:
 Code:
Dim $sDOMAIN,$sSpooler
$sDOMAIN="westcare"
$sSpooler="\\wcps1\"


; ----------------------------INI printer handing start--------------------------
$ID = Left(@WKSTA, 4)
$PrinterList = Split(ReadProfileString('C:\printers.ini', $ID, 'Printers'), ';')
$DefPrinter = ReadProfileString('C:\printers.ini', $ID, 'Default')
For Each $Printer in $PrinterList
	myAddPrinter($Printer)
Next
If $DefPrinter mySetDefaultPrinter($DefPrinter) EndIf
; ----------------------------INI printer handing end----------------------------


; --------------------------Group printer handing start--------------------------
;set index to 0 for looping through groups
$iIndex = 0

;get first group name
$sGroup=EnumGroup($Index)
While Len($sGroup) AND @ERROR=0
	;if group name starts with print- or printd-
	If (InStr($sGroup,$sDOMAIN+"\print-")=1) OR (InStr($sGroup,$sDOMAIN+"\printd-")=1)
		$sPrinter=SubStr($sGroup,InStr($sGroup,"-")+1) ; Note, this won't work if you have "-" in the domain name
		myAddPrinter($sSpooler+$sPrinter)
		; Try and set the printer as default if requested
		If InStr($sGroup,$sDOMAIN+"\printd-")=1 mySetDefaultPrinter($sSpooler+$sPrinter) EndIf
	EndIf
	$iIndex=$iIndex+1		 ;increase the loop counter by 1
	$sGroup=EnumGroup($iIndex)	 ;get next group name

; loop until end of groups list
Loop
; --------------------------Group printer handing end----------------------------

; -------------------------User defined function start---------------------------
Function myAddPrinter($sPath)
	; Static variable, implemented as global
	If Not IsDeclared($__DonePrinters) Global $__DonePrinters $__DonePrinters=@CRLF EndIf

	If InStr($__DonePrinters,@CRLF+$sPath+@CRLF)
		; Printer has already been added - no point in doing it again.
	Else
		; Add printer and make sure it’s successful
		If AddPrinterConnection($sPath)
			; Display error message and text
			"Error Adding Printer: "+$ssPath+@CRLF
			"Error: "+@SERROR+@CRLF
		Else
			"Added printer: "+$sPath+@CRLF	; Display success message
			$__DonePrinters=$__DonePrinters+$sPath+@CRLF		; Record success
		EndIf
	EndIf
EndFunction

Function mySetDefaultPrinter($sPath)
	; Static variables, implemented as globals
	If Not IsDeclared($__DonePrinters) Global $__DonePrinters $__DonePrinters=@CRLF EndIf
	If Not IsDeclared($__DoneDefault) Global $__DoneDefault $__DoneDefault=0 EndIf

	; If the printer was added OK and we have not already set the default...
	If InStr($__DonePrinters,@CRLF+$sPath+@CRLF) AND $__DoneDefault=0
		If SetDefaultPrinter($sPath)
			; Display error message and text
			"Error Setting Default Printer: "+$sPath+@CRLF
			"Error: "+@SERROR+@CRLF
		Else
			"Set default to: "+$sPath+@CRLF	; Display success message.	
			$__DoneDefault=1
		EndIf
	EndIf
EndFunction
; -------------------------User defined function end-----------------------------


As you want to add the printer in two different places I've converted the common code to user defined functions (UDFs) called myAddPrinter() and mySetDefaultPrinter().

The variables that track the list of printers added must be preserved between function calls. In other languages you would declare a local static variable, however this feature is not available in KiXtart so we use global variables instead.

Other than that the code is identical, just shuffled about a bit.

You might still want to change the already-mapped check to using the PriMapState() function, as it will allow you to avoid the cost associated with removing printers which you are then going to add again.

BTW, in this code if the default printer is defined in the INI file and is set OK then the default printer defined by group is ignored. If you'd prefer the group defined default printer to take priority then just swap the INI and group code around so that the group code executes first.

Top
#198123 - 2010-03-22 01:36 PM Re: expertise sought for tweaking print mapping [Re: Richard H.]
BReed Offline
Fresh Scripter

Registered: 2010-03-17
Posts: 10
Loc: nc
Thanks Richard, when I see your code laid out, I'm able to see what's happening and understand it much better. I'm still far from being able to whip out something like that on my own, but with your help and guidance and this site, I'm definitely making progress with my comprehension of how it should work as opposed to how I think it's supposed to work.

Everyone's input has been an invaluable lesson and I thank you all very much in helping a new wannabe-scripter such as myself make more sense of it all

Top
Page 1 of 1 1


Moderator:  Glenn Barnas, NTDOC, Arend_, Jochen, Radimus, Allen, ShaneEP, Ruud van Velsen, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 601 anonymous users online.
Newest Members
M_Moore, BeeEm, min_seow, Audio, Hoschi
17883 Registered Users

Generated in 0.187 seconds in which 0.143 seconds were spent on a total of 13 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org