Page 1 of 1 1
Topic Options
#195492 - 2009-08-20 06:44 PM Script to install printer based on IP is not running on logon
getelevated Offline
Fresh Scripter

Registered: 2009-08-20
Posts: 8
Loc: Boston
Hello,

I have a portion of a script that is not working as expected. The script installs printers based on IP address and I got it from this thread: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=195486&fpart=1 (thanks Glenn). It was very helpful for a customer office move that we just went through.

We put the script together and during our testing all of the printers were installed flawlessly on each subnet. But now that the move has been completed there is one strange issue. When the users first log on, the script starts to run and the "No printers were mapped!" comment appears. But the users should have received at least one printer. Now here's the tricky part; if I manually run the kix script when the user is logged in (going to the sysvol share via command line) the printers get mapped correctly. Any ideas?

Here is the script, stating with the select state for the AD site that this office is in. Everything works but the printer install on login:
 Code:
CASE @Site = "ADSITE"
  ? "Logging in from Site"

   WriteValue("Software\Microsoft\Windows\CurrentVersion\Internet Settings", "MaxConnectionsPerServer", "6", "REG_DWORD")

 ; Map S drive for application
 use s: "\\DC1\Applications\APPS"


   SELECT

   CASE INGROUP("Facilities")
    use g: "\\DC2\Facilities"

   CASE INGROUP("Technology")
    use g: "\\DC2\Tech"

   CASE INGROUP("Call Center")
    use g: "\\DC2\TSR"

   CASE INGROUP("Finance")
    use g: "\\DC2\Finance"

   CASE INGROUP("Operations")
    use g: "\\DC2\Operations"

   CASE INGROUP("Human Resources")
    use g: "\\DC2\HumanResources"

   CASE INGROUP("Employee Development")
    use g: "\\DC2\Corporate Training"

   CASE INGROUP("Marketing")
    use g: "\\DC2\MKT"

   ENDSELECT

 IF INGROUP("Group1")
    use U: "\\server\drive"
 ENDIF

 IF INGROUP("Group1")
    use I: "\\DC2\Intranet"
    use w: "\\Intranet\Documents"
 ENDIF
  
 IF INGROUP("Case Files")
   use r: /delete
   use r: "\\server6\share"
 ENDIF


; Copy file to user directory to run script once

IF EXIST ("%appdata%\Microsoft\printers.txt") 
	; do nothing
  ELSE
   copy "\\DC2\PrintTemp$\printers.txt" "%appdata%\Microsoft\printers.txt" /c
   sleep 2

; Delete all existing Network Printer Connections

  function DelPrinterConnections()
   dim $c,$bk,$conn
   $c=0
   $bk="HKEY_CURRENT_USER\Printers\Connections"
   $conn=enumkey($bk,$c)
   while @error=0
    $c=$c+0
    $conn=delkey($bk+"\"+$conn)
    $conn=enumkey($bk,$c)
   loop
  endfunction

DelPrinterConnections()


; Install new printers based on workstation subnet

; Break On
; Uses an INI file for subnet/printer mapping
; The INI file in this example is called NetPrint.ini, and uses one section
; called MAPPINGS. Each value consists of a comma-delimited pair of data
; representing the network/mask and printer share UNC in the format
; sitename=w.x.y.z/mask,\\server\printer

$Mapped = 0					; value showing that printer was not mapped

$MyIP = Join(Split(@IPADDRESS0, ' '), '')	; Get the local IP address, removing spaces

; Load an array from the INI file
$Mappings = EnumIni('.\netprint.ini', 'MAPPINGS')

For Each $SiteName in $Mappings

  ; create a 2-element array by splitting the data at the comma
  ; element 0 contains the network/mask, and element 1 contains the printer UNC
  $NetPrint = Split(ReadProfileString('.\netprint.ini', 'MAPPINGS', $SiteName), ',')

  ; see if the local IP is inside the network
  If InSubnet($MyIP, $NetPrint[0])

    ; these print statements are for diagnostic/testing
 ?  'My ip address (' $MyIP ') exists in the ' $SiteName ' site (' $NetPrint[0] ')' ?
 ?   'Mapping printer ' $NetPrint[1] ?

    ; make the printer connection
    AddPrinterConnection($NetPrint[1])

    ; show that at least 1 printer mapped successfully
    If Not @ERROR
      $Mapped = 1
    EndIF

  EndIF

Next


If Not $Mapped
 ? 'No printers were mapped!' ?
EndIf

; do not modify anything after this line!!!

;; 
;;====================================================================== 
;; 
;;FUNCTION       InSubnet() 
;; 
;;ACTION         Determines if a specific IP address is in a subnet 
;; 
;;AUTHOR         Glenn Barnas 
;; 
;;VERSION        1.0 / 2008/01/20 
;; 
;;SYNTAX         InSubnet(Address, Network) 
;; 
;;PARAMETERS     Address - REQUIRED, IP address in dotted-decimal (w.x.y.z) 
;; 
;;		 Network - REQUIRED, Network in CIDR format (w.x.y.z/mask) 
;; 
;;REMARKS         
;; 
;;RETURNS        1 if ip address is in the defined subnet, 0 otherwise 
;; 
;;DEPENDENCIES   none 
;; 
;;TESTED WITH    W2K, WXP, W2K3, Vista, X64 
;; 
;;EXAMPLES       If InSubnet('192.168.12.243', '192.168.8.0/21') 
;;		   'Is in subnet!' ? 
;;		 EndIf 
; 
Function InSubnet($_IPAddr, $_Network)
 
  Dim $_aAdd				; array of address values 
  Dim $_Mask				; Mask value 
  Dim $_Hosts				; hosts in subnet 
 
  ; Convert the supplied IP address to a double value representing the decimal address 
  $_aAdd = Split($_IPAddr, '.')
  $_IPAddr = (CDbl($_aAdd[0]) * 16777216.0) + (CDbl($_aAdd[1]) * 65536.0) + (CDbl($_aAdd[2]) * 256.0) + (CDbl($_aAdd[3]) * 1.0)
 
  ; Convert the network from a w.x.y.z/mask format to a decimal value 
  ; this is the starting network address value 
  $_Network = Split($_Network, '/')
  $_Mask = Val($_Network[1])
  $_aAdd = Split($_Network[0], '.')
  $_Network = (CDbl($_aAdd[0]) * 16777216.0) + (CDbl($_aAdd[1]) * 65536.0) + (CDbl($_aAdd[2]) * 256.0) + (CDbl($_aAdd[3]) * 1.0)
 
  ; Set the number of hosts in the defined network 
  $_Hosts = 1.0
  For $_I = 31 to $_Mask Step -1
    $_Hosts = ($_Hosts * 2.0)
  Next
 
  ; return the value  
  $InSubnet = 0
  If $_IPAddr >= $_Network And $_IPAddr < ($_Network + $_Hosts)
    $InSubnet = 1
  EndIf
 
  Exit 0
 
EndFunction
 



;; 
;;====================================================================== 
;; 
;;FUNCTION       EnumIni() 
;; 
;;ACTION         Enumerates sections or keys of an INI file 
;; 
;;AUTHOR         Glenn Barnas  
;; 
;;VERSION        2.0 
;; 
;;DATE CREATED   2003/11/17 
;; 
;;DATE MODIFIED  2004/10/16 
;; 
;;SYNTAX         EnumIni(File [, Section]) 
;; 
;;PARAMETERS     File - 	REQUIRED, path/name of INI file to examine 
;; 
;;               Section -	OPTIONAL, Section name to parse 
;; 
;;REMARKS        Returns an array containing the sections in an INI file, or 
;;               an array of key names in a specified section. Errors are returned 
;;               for non-existant files or INI file reads. If the specified file 
;;               contains no sections, or the specified section contains no keys, 
;;               the UDF exits with error 13 and returns a null array. Thus, a For-Each loop 
;;               will properly perform no iterations if no data is returned. 
;; 
;;               CAUTION - Error 13 is returned for empty files, or nonexistant sections. 
;;                         This is not necessarily a "failure". 
;; 
;;RETURNS        Array of sections or keys in a section 
;; 
;;DEPENDENCIES   none 
;; 
;;TESTED WITH    Kix 4.2+, NT4, W2K, WXP, W2K3 
;; 
;;EXAMPLES       $Sections = EnumIni('.\config.ini') 
;;               $Keys = EnumIni('.\config.ini', 'Common') 
; 
Function EnumIni($_fSrcFile, OPTIONAL $_fSectName)
 
  Dim $_fSectList
 
  ; die if the file doesn't exist 
  If Exist($_fSrcFile) = 0
    Exit 2
  EndIf
 
  ; Get the list of sections or keys 
  $_fSectList = ReadProfileString($_fSrcFile, $_fSectName, '')
  ; Return if error occurred 
  If @ERROR
    Exit @ERROR
  EndIf
 
  ; If len is >0, return an array of sections 
  ; If len is 0, either no sections or keys exist, or an invalid section name was specified. Return nothing. 
  If Len($_fSectList) > 0
    $EnumIni = Split(Left($_fSectList,len($_fSectList)-1), Chr(10))
    Exit 0
  EndIF
 
  ; return an error here for value not found (no sections or no keys in section) 
  Exit 13
 
EndFunction 

ENDIF

Top
#195505 - 2009-08-21 02:02 PM Re: Script to install printer based on IP is not running on logon [Re: getelevated]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4403
Loc: New Jersey
I ran your code through KGen to get a Sanity and CodeMap report. Ignoring the "Undeclared Variable" warnings because I don't have your complete script, I got the following:
 Code:
Warning: Variable referenced inside string.
              Variable Name: $
                In function: Main
         Referenced on line: 59
     59: copy "\\DC2\PrintTemp$\printers.txt" "%appdata%\Microsoft\printers.txt" /c

If you don't declare NoVarsInStrings, this could cause a problem copying the file. I assume this is some kind of tag file indicating that some task has completed. I'm not a big fan of this concept. Use a reg key something like SOFTWARE\MyCompany\StatusID:Value in HKLM or HKCU. Faster and less susseptible to user interaction.

CodeMap shows the following:
 Code:
000001: Main
000010:  Select
000036:  EndSelect
000038:  IF INGROUP("Group1")
000040:  EndIf
000042:  IF INGROUP("Group1")
000045:  EndIf
000047:  IF INGROUP("Case Files")
000050:  EndIf
000055:  IF EXIST ("%appdata%\Microsoft

000063: Function: DelPrinterConnections
 - WARNING: Open If when defining function. 1
<snip>
WARNING: 1 Unterminated If statement(s)!
This is why I use KGen even for the simplest scripts..


Your If Exist is backwards, in addition to missing a closing EndIf. Since we're troubleshooting, change this to
 Code:
If Exist('%appdata%\Microsoft\printers.txt')
  'Tag file exists - not mapping!'
Else
 . . .
That might provide a clue or three.. A better implementation (after the diagnostic process is complete) would be
 Code:
If Not Exist('%appdata%\Microsoft\printers.txt')
and eliminate the empty If clause.

I'm also troubled by your DelPrinterConnections logic. You enumerate the values in a registry key and delete them. Without creating and then deleting a bunch of registry keys to test this, I'm going to simply discuss the illogicical part by commenting your code. My concerns are in ALL CAPS
 Code:
function DelPrinterConnections()
  Dim $C, $Bk, $Conn                           ; Declare index pointer, BaseKey, & Connection vars
  $C=0                                         ; initialize index pointer
  $Bk='HKEY_CURRENT_USER\Printers\Connections' ; initialize Base Key
  $Conn = EnumKey($Bk,$C)                      ; locate the first subkey in the key
  While @ERROR = 0                             ; loop until EOF error

; SINCE WE ARE ADDING NOTHING TO NOTHING, WHAT'S THE POINT OF $C??
    $C = $C + 0                                ; increment pointer - BUT NOT REALLY!!!

; REUSING AN ACTIVE VARIABLE CAN BE DANGEROUS - DECLARE AND USE $RC INSTEAD
    $Conn = DelKey($bk + '\' + $Conn)          ; Delete the key

; HERE'S MY REAL CONCERN. YOU JUST DELETED KEY 0, AND NOW YOU'RE ENUMERATING KEY 0.
; A. IT DOESN'T EXIST, SO RETURNS AN ERROR AND THE FUNCTION EXITS, DELETING ONLY ONE PRINTER KEY
; B. THE SECOND KEY MOVES UP TO BE ENUMERATED IN POSITION 0. IF THIS IS THE CASE, REMOVE THE
; "$C = $C + 0" LINE, THE $C DECLARATION, AND REPLACE ALL OTHER REFERENCES TO $C WITH 0 (ZERO)
    $Conn = EnumKey($Bk, $C)                   ; Enumerate the NEXT?? key ? ? ? ? ? ?
  Loop
EndFunction
Glenn
_________________________
Actually I am a Rocket Scientist! \:D

Top
#195552 - 2009-08-24 04:56 PM Re: Script to install printer based on IP is not running on logon [Re: Glenn Barnas]
getelevated Offline
Fresh Scripter

Registered: 2009-08-20
Posts: 8
Loc: Boston
Thanks for the reply Glenn.

The text copy portion of the script is working, both on initial logon and if I manually run the script. The If statement is closed, that ENDIF is just not included in the portion I pasted above. That's the only portion of the script that I know is working, since I routinely remove that text file for testing.

The printer deletion script came from here: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=142166&site_id=1#import but now that you mention it, the +0 enumeration does not make much sense (I blame my lack of caffeine and trying to put together a script made up of bits and pieces from other posts...)

Anyway, aside from the errors in the Deletion portion of the script that doesn't solve my problem. I have commented out that portion of the script in testing and it still does not correctly run during the logon process. But it does work fine when run manually. I still end up with just the No Printers Mapped result, but when the script is run from the command line it maps as it should. I'm trying to figure out where the issue may lie but I'm having trouble since it works manually.

Regards,
Conor

Top
#195553 - 2009-08-24 05:38 PM Re: Script to install printer based on IP is not running on logon [Re: getelevated]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4403
Loc: New Jersey
When I encouner unusual things like this, I break the code down into smaller chunks and add diag messages. Simple things, like printing out section numbers so I know where a process is, to displaying values of variables - even when I think I know what they are - er - should be! While unlikely, it's possible that the environment was not set when Kix ran during logon but is later when run from the command prompt. Display the content of the %appdata% variable, and the @IPADDRESS as well - are they valid? Do they contain what you expect?

The $C=0+0 was discussed in the thread you referenced, but incrementing by 0.5 is not correct. As I thought, the values move up when one is deleted, so referencing zero all the time is correct.

Unless you've cut and pasted many separate sections of code into your example, you're EndIf is either missing or out of place. You should have an EndIf before any of the functions start, and not later on in the code. Also, while valid, placing functions inline with your code makes the application more difficult to troubleshoot - especially when they are within other code pairs like loops or If/Endifs. Put all your functions first or last. I create my core code, then include functions dedicated to the script, and then those that are from the shared-code library. Not right or wrong, just helps maintain hairs in your head.

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

Top
#195554 - 2009-08-24 06:13 PM Re: Script to install printer based on IP is not running on logon [Re: Glenn Barnas]
getelevated Offline
Fresh Scripter

Registered: 2009-08-20
Posts: 8
Loc: Boston
Good points. I'll start with the @IPAddress as I think that's where the issue is.

Thanks for the suggestions. It's been a while since I've done this much with Kix and I appreciate the input. I'll let you know how it goes.

Top
#195558 - 2009-08-24 10:23 PM Re: Script to install printer based on IP is not running on logon [Re: Glenn Barnas]
getelevated Offline
Fresh Scripter

Registered: 2009-08-20
Posts: 8
Loc: Boston
I did some testing with printing the variables to the screen. I think the problem is here:

 Code:

For Each $SiteName in $Mappings

  ; create a 2-element array by splitting the data at the comma
  ; element 0 contains the network/mask, and element 1 contains the printer UNC
  $NetPrint = Split(ReadProfileString('.\netprint.ini', 'MAPPINGS', $SiteName), ',')

  ; see if the local IP is inside the network
  If InSubnet($MyIP, $NetPrint[0])

    ; these print statements are for diagnostic/testing
    'My ip address (' $MyIP ') exists in the ' $SiteName ' site (' $NetPrint[0] ')' ?
    'Mapping printer ' $NetPrint[1] ?

    ; make the printer connection
    AddPrinterConnection($NetPrint[1])

    ; show that at least 1 printer mapped successfully
    If Not @ERROR
      $Mapped = 1
    EndIF

  EndIF

Next


When the user logs in initially, this doesn't run. I did a
 Code:
 ? $SiteName ? 
inside that For Each and it doesn't show on logon. It does show up and run correctly when run manually after the user logs in. Anyone seen this behavior before?

Top
#195559 - 2009-08-24 10:29 PM Re: Script to install printer based on IP is not running on logon [Re: getelevated]
Gargoyle Offline
MM club member
*****

Registered: 2004-03-09
Posts: 1597
Loc: Valley of the Sun (Arizona, US...
What is $Mappings coming from. That is what holds you $SiteName.
_________________________
Today is the tomorrow you worried about yesterday.

Top
#195562 - 2009-08-24 10:58 PM Re: Script to install printer based on IP is not running on logon [Re: Gargoyle]
getelevated Offline
Fresh Scripter

Registered: 2009-08-20
Posts: 8
Loc: Boston
It's the result of another function. That detail is below, but it's in full context in my first post in the thread.

 Code:
$Mappings = EnumIni('.\netprint.ini', 'MAPPINGS')




;; 
;;====================================================================== 
;; 
;;FUNCTION       EnumIni() 
;; 
;;ACTION         Enumerates sections or keys of an INI file 
;; 
;;AUTHOR         Glenn Barnas  
;; 
;;VERSION        2.0 
;; 
;;DATE CREATED   2003/11/17 
;; 
;;DATE MODIFIED  2004/10/16 
;; 
;;SYNTAX         EnumIni(File [, Section]) 
;; 
;;PARAMETERS     File - 	REQUIRED, path/name of INI file to examine 
;; 
;;               Section -	OPTIONAL, Section name to parse 
;; 
;;REMARKS        Returns an array containing the sections in an INI file, or 
;;               an array of key names in a specified section. Errors are returned 
;;               for non-existant files or INI file reads. If the specified file 
;;               contains no sections, or the specified section contains no keys, 
;;               the UDF exits with error 13 and returns a null array. Thus, a For-Each loop 
;;               will properly perform no iterations if no data is returned. 
;; 
;;               CAUTION - Error 13 is returned for empty files, or nonexistant sections. 
;;                         This is not necessarily a "failure". 
;; 
;;RETURNS        Array of sections or keys in a section 
;; 
;;DEPENDENCIES   none 
;; 
;;TESTED WITH    Kix 4.2+, NT4, W2K, WXP, W2K3 
;; 
;;EXAMPLES       $Sections = EnumIni('.\config.ini') 
;;               $Keys = EnumIni('.\config.ini', 'Common') 
; 
Function EnumIni($_fSrcFile, OPTIONAL $_fSectName)
 
  Dim $_fSectList
 
  ; die if the file doesn't exist 
  If Exist($_fSrcFile) = 0
    Exit 2
  EndIf
 
  ; Get the list of sections or keys 
  $_fSectList = ReadProfileString($_fSrcFile, $_fSectName, '')
  ; Return if error occurred 
  If @ERROR
    Exit @ERROR
  EndIf
 
  ; If len is >0, return an array of sections 
  ; If len is 0, either no sections or keys exist, or an invalid section name was specified. Return nothing. 
  If Len($_fSectList) > 0
    $EnumIni = Split(Left($_fSectList,len($_fSectList)-1), Chr(10))
    Exit 0
  EndIF
 
  ; return an error here for value not found (no sections or no keys in section) 
  Exit 13
 
EndFunction 

Top
#195565 - 2009-08-24 11:40 PM Re: Script to install printer based on IP is not running on logon [Re: getelevated]
Glenn Barnas Administrator Offline
KiX Supporter
*****

Registered: 2003-01-28
Posts: 4403
Loc: New Jersey
You reference the location of the INI file indirectly, as in ".\filename". I'd sprinkle a few @CURDIR and @SCRIPTDIR macros around and see if the locations are different between running during logon and interactively. \:\)

Also - try this:
 Code:
$Mappings = EnumIni('.\netprint.ini', 'MAPPINGS')
@SERROR ?
- see if "The command completed successfully" or not.

Glenn

PS - you do know that our commercial Kix login script maps resources by AD Site, OU, Group, and Network Subnet, and is a free download, right? ;\)
_________________________
Actually I am a Rocket Scientist! \:D

Top
#195590 - 2009-08-25 04:40 PM Re: Script to install printer based on IP is not running on logon [Re: Glenn Barnas]
getelevated Offline
Fresh Scripter

Registered: 2009-08-20
Posts: 8
Loc: Boston
The netprint.ini file was it. The .\netprint.ini call was failing on login. I added the UNC path and it worked. Thanks for the help.

I do know the script maps from AD Sites, OU, Group, etc as I am using that extensively throughout the rest of the script. I didn't know that it worked by subnet but I'll check part out.

Thanks again!

Top
Page 1 of 1 1


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

Who's Online
0 registered and 2009 anonymous users online.
Newest Members
fgarcia, Viginette, ManuvdWielNL, Sir_Barrington, batdk82
17889 Registered Users

Generated in 0.164 seconds in which 0.129 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