Witto
(MM club member)
2006-08-24 03:59 PM
Yet another printer script

I was thinking about just another printer installation script, installing printers depending on the network/subnet during logon.
Let us presume a network with just some NT4, and mainly W2K and XP workstations. Also a Terminal server is present.
I was thinking about using WTSManager.dll for the terminal sessions and IsInsubnet() to find the subnet (see UDF lib, thanks Jens).
The subnet will be found via a select statement.
When found, maybe I can use an ini file to install printer(s) and maybe fax and set the default printer. But I am unsure about the structure this ini file should have.
I am sure this can be much better. Any reaction or comment that can help to make this script better or to simplify it is welcome. Thanks.
If NOT @LOGONMODE
Break ON
EndIf
Dim $SO
$SO = SetOption("Explicit","On")
$SO = SetOption("NoMacrosInStrings","On")
$SO = SetOption("NoVarsInStrings","On")

Dim $IPAddress
; Is this NOT a Windows Terminal (Citrix) session?
If NOT @TSSESSION
; Is this NOT Windows NT4?
If NOT @PRODUCTTYPE = "Windows NT Workstation"
; Enumerate IP Addresses
Dim $NIC
$NIC = 0
While EnumIPInfo($NIC,0,0)
$IPAddress = EnumIPInfo($NIC,0,0)
; Install Printers
InstallPrinters($IPAddress)
$NIC = $NIC + 1
Loop
; This IS a Windows NT4
Else
; Let us presume this computer has only one IP Address
$IPAddress = @IPADDRESS0
; Install Printers
InstallPrinters($IPAddress)
EndIf
; This is a Windows Terminal session (Citrix)
Else
; ===========================================================================================
; To use the COM Object wtsScript,
; WTSManager.dll has to be registered on the terminal servers
; http://kixhelp.com/Downloads/wtsmanager.zip
; ===========================================================================================
; Get the IP Address of the real workstation
Dim $oWts
$oWts = CreateObject("WTSManager.Shell")
$IPAddress = $oWts.MyIPAddress
If $IPAddress = ""
; Most probably WTSManager.dll is not registered on this terminal server
Exit 0
EndIf
; Install Printers
InstallPrinters($IPAddress)
EndIf

Function InstallPrinters($IP)
Select
Case IsInSubnet($IP,'10.17.1.32','255.255.255.224')
; Do Stuff
Case IsInSubnet($IP,'10.17.1.64','255.255.255.224')
; Do Stuff
Case IsInSubnet($IP,'10.17.1.96','255.255.255.224')
; Do Stuff
Case 1
; Do Stuff
EndSelect
EndFunction


NTDOCAdministrator
(KiX Master)
2006-08-24 09:51 PM
Re: Yet another printer script

Well I'll wait for Richard or Jooel to speak up first.

Witto
(MM club member)
2006-08-24 09:57 PM
Re: Yet another printer script

Thanks anyway for the reply

LonkeroAdministrator
(KiX Master Guru)
2006-08-24 10:10 PM
Re: Yet another printer script

nothing much to say.
other than I would probably have used moan() instead of isinsubnet
you know, just for fun.
http://www.kixtart.org/ubbthreads/showflat.php?Cat=0&Number=83638

not sure what the fax comment there was...
anyways, if you are going to use INI (which would be a good thing), your install printers might look like this:
Code:

Function InstallPrinters($IP)
dim $subnet, $printer, $
$subnet = moan($IP,"255.255.255.224")
for each $printer in split(readprofilestring("theinifile",$subnet),chr(10))
if len($printer)
if not primapstate(readprofilestring("theinifile",$subnet,$printer))
$ = addprinterconnection(readprofilestring("theinifile",$subnet,$printer))
endif
endif
next
EndFunction



and your ini would have sections for subnets.
the primapstate is not needed but if having large amount of printers and/or users, it should speed up your script a lot.


Witto
(MM club member)
2006-08-24 10:25 PM
Re: Yet another printer script

Thanks for your reply. I already noticed that checking the registry to see if a printer is installed speeds up the script. But it is good to know there is an UDF that can be used.
We have multifunctionals that can be used as network fax. You know that these things just install as a network printer.


Witto
(MM club member)
2006-08-24 10:53 PM
Re: Yet another printer script

Code:

for each $printer in split(readprofilestring("theinifile",$subnet),chr(10))


ReadProfileString apparently requires 3 parameters


LonkeroAdministrator
(KiX Master Guru)
2006-08-24 11:07 PM
Re: Yet another printer script

oh... you right...
add ,"" to the end.


Witto
(MM club member)
2006-08-24 11:12 PM
Re: Yet another printer script

Just another thought. If it would be possible to catch the Network Address in a variable, in stead of the IP Address, the script would be more flexible and would not have to be adapted as more subnets are created. Also the subnet mask would be of less of no importance.
With EnumIPInfo, you can get the IP Address and the subnet mask. In theory, the network address can be calculated.
But I do not think this is possible on an NT4 or with WTSManager.dll on a terminal server.


LonkeroAdministrator
(KiX Master Guru)
2006-08-24 11:19 PM
Re: Yet another printer script

well, my scriptlet does exactly that.
you provide the ip and mask and it calculates the subnet.
then you have the subnets in the ini and which that same scriptlet reads from.
no need to change the script at all at any stage.


Witto
(MM club member)
2006-08-24 11:39 PM
Re: Yet another printer script

True, but the subnet mask is hard coded.
How does your ini file look like?
Code:

[10.17.1.32]
DefaultPrinter=\\Server\Printer1
ColorPrinter=\\Server\Printer2
Fax1=\\Server\Printer3

[10.17.1.64]
DefaultPrinter=\\Server\Printer4
ColorPrinter=\\Server\Printer5
Fax1=\\Server\Printer6

[10.17.1.96]
DefaultPrinter=\\Server\Printer7
ColorPrinter=\\Server\Printer8
Fax1=\\Server\Printer9


I just tried to get some screen output
Code:

InstallPrinters('10.17.1.32')
?
InstallPrinters('10.17.1.64')
?
InstallPrinters('10.17.1.96')

Function InstallPrinters($IP)
Dim $subnet, $printer, $
$subnet = moan($IP,"255.255.255.224")
For Each $printer In Split(ReadProfileString("C:\Script\PrinterScript\Printers.ini",$subnet,""),Chr(10))
? $Printer
If Len($printer)
? "You been here"
If NOT primapstate(ReadProfileString("C:\Script\PrinterScript\Printers.ini",$subnet,$printer))
;$ = AddPrinterConnection(ReadProfileString("C:\Script\PrinterScript\Printers.ini",$subnet,$printer))
? ReadProfileString("C:\Script\PrinterScript\Printers.ini",$subnet,$printer)
? "You not been here"
EndIf
EndIf
Next
EndFunction


I think I am missing something...
$Printer is the section...


LonkeroAdministrator
(KiX Master Guru)
2006-08-25 12:29 AM
Re: Yet another printer script

in your ini, $printer would be either DefaultPrinter, ColorPrinter or Fax.
and, yes. the subnetmask is hardcoded cause you had it that way.


Witto
(MM club member)
2006-08-25 12:37 AM
Re: Yet another printer script

I am affraid to say that in the script like I modified it as a test, $Printer returns the section.
Indeed, I hardcoded the subnet mask, but better would be to get rid of that. EnumIPInfo would enable me to do so, but I do not think I can do this on a Windows NT4 (@IPADDRESS0) and certainly not in a terminal session (WTSManager.dll), as in that case, only the IP address is returned?


LonkeroAdministrator
(KiX Master Guru)
2006-08-25 01:14 AM
Re: Yet another printer script

oh.
you are providing the subnet to the udf.
so it fails.
MOAN does not like you to play with it's feelings.
provide a real IP address as parameter and it will work fine.


Witto
(MM club member)
2006-08-25 01:43 AM
Re: Yet another printer script

Guess you are right I did something completely wrong testing this.
As I read in the examples of moan(), I would have to write: moan($IP,,"255.255.255.224")
To get the Network Address as return value?
Code:

InstallPrinters('10.17.1.33')
Function InstallPrinters($IP)
Dim $subnet, $printer, $
$subnet = moan($IP,,"255.255.255.224")
? $Subnet
EndFunction



LonkeroAdministrator
(KiX Master Guru)
2006-08-25 01:47 AM
Re: Yet another printer script

yup. your turn to be right
again.


Witto
(MM club member)
2006-08-25 01:57 AM
Re: Yet another printer script

But
Code:

? $Subnet


does not like me
Code:

ERROR : Error in expression: this type of array not supported in expressions.!
Script: D:\Scripts\PrinterScript\Printers.kix
Line : 7


Line 7 because there is a "Break On" and a blank line on top of the script

Network ID's and their respective subnet masks are things that are known to me. So if there would be a way I could write an INI that contains
- Network ID
- Subnet Mask
- Printer Share Names (\\server\printer)
- Reference to default printer
The script itself should just return the IP Address of the computer. From the moment the IP Address of a computer is known, it should be compared to Network ID's and Subnet Masks in the ini file to find the section needed, then all keys and values in that section could be read to install the printers and set the default printer.
I think I will take a good night sleep to think about this.
Thanks for all your replies. I really like this BBS.


Gargoyle
(MM club member)
2006-08-25 03:11 AM
Re: Yet another printer script

Well if you know the subnets why don't you just do a comparison of that for the ini file. Strip off whatever is the host portion and off you go. Extremly easy if it is /24 if not I can take any given subnet mask for a given network and provide all of the subnets available.

LonkeroAdministrator
(KiX Master Guru)
2006-08-25 08:21 AM
Re: Yet another printer script

witto, I need try that out.
it shouldn't surely output any array.


Witto
(MM club member)
2006-08-26 08:08 AM
Re: Yet another printer script

After two nights of sleep and some testing, this will be my challenge:
I am thinking about an INI file like this
[10.17.1.32,255.255.255.224]
DefaultPrinter=\\Server\Printer1
ColorPrinter=\\Server\Printer2
Fax1=\\Server\Printer3

[10.17.1.64/255.255.255.224]
DefaultPrinter=\\Server\Printer4
ColorPrinter=\\Server\Printer5
Fax1=\\Server\Printer6

[10.17.1.96/27]
DefaultPrinter=\\Server\Printer7
ColorPrinter=\\Server\Printer8
Fax1=\\Server\Printer9

To do:
Create a function with as parameter the IP Address of the workstation: AddPrinterConnections($IPAddress)
Check sections one by one
If format section is wrong, check next
Check if IP Address is part of network defined in section
If error is thrown, set error and check next
If IP Address not part of network defined in section, check next
If success:
- check keys one by one in section
- Add printers if not yet installed (set error if thrown)
- Install default printer if not yet installed (set error if thrown)
- Possible additional reasons for not setting default printer: parallel or usb printer found
- Exit function


NTDOCAdministrator
(KiX Master)
2006-08-26 08:23 AM
Re: Yet another printer script

I guess I'm missing something here with printers.
I've worked in a few companies including one with thousands of
workers and at none of these places did we automate installing
printers for users.

Once a printer is installed (everyone that has probably been at
work for more than a few days) then all that should be left is
the onesey - twosey printer adds which many users can do on
their own, and for those that can't the helpdesk can walk them
through it typically in a minute or less, a few minutes at most
for the really chatty users.

If you were changing print servers I could see doing some automation,
but for stuff that is already probably 95% in place
I must ask WHY?

Just seems like there must be other projects and maintenance that
would benifit more from your hard work than figuring out some
method to automate printer installs for people that mostly
already should have their printers installed.


Witto
(MM club member)
2006-08-27 02:57 AM
Re: Yet another printer script

I am not able to test this during the next days or weeks, but I presume this is (almost) working code
The script:
If NOT @LOGONMODE
Break ON
EndIf
Dim $SO
$SO = SetOption("Explicit","On")
$SO = SetOption("NoMacrosInStrings","On")
$SO = SetOption("NoVarsInStrings","On")

Dim $IPAddress

; Is this NOT a Windows Terminal (Citrix) session?
If NOT @TSSESSION
; Is this NOT Windows NT4?
If NOT @PRODUCTTYPE = "Windows NT Workstation"
; Enumerate IP Addresses
Dim $NIC
$NIC = 0
While EnumIPInfo($NIC,0,0)
$IPAddress = EnumIPInfo($NIC,0,0)
; Add Printers
AddPrinterConnections($IPAddress)
$NIC = $NIC + 1
Loop
; This IS a Windows NT4
Else
; Let us presume this computer has only one IP Address
$IPAddress = @IPADDRESS0
; Add Printers
AddPrinterConnections($IPAddress)
EndIf
; This is a Windows Terminal session (Citrix)
Else
; ===========================================================================================
; To use the COM Object wtsScript,
; WTSManager.dll has to be registered on the terminal servers
; http://kixhelp.com/Downloads/wtsmanager.zip
; ===========================================================================================
; Get the IP Address of the real workstation
Dim $oWts
$oWts = CreateObject("WTSManager.Shell")
$IPAddress = $oWts.MyIPAddress
If $IPAddress = ""
; Most probably WTSManager.dll is not registered on this terminal server
Exit 0
EndIf
; Add Printers
AddPrinterConnections($IPAddress)
EndIf

; Function AddPrinterConnection
; Dependencies; IsInSubnet, PriMapState
Function AddPrinterConnections($IPAddress)
Dim $Section, $NetworkID, $Mask, $Key, $Error
$Error = 0
For Each $Section In Split(ReadProfileString("PathTo\Printers.ini","",""),Chr(10))
Select
Case InStr($Section,",")
If Ubound(Split($Section,",")) = 1
$NetworkID = Split($Section,",")[0]
$Mask = Split($Section,",")[1]
EndIf
Case InStr($Section,"/")
If Ubound(Split($Section,"/")) = 1
$NetworkID = Split($Section,"/")[0]
$Mask = Split($Section,"/")[1]
EndIf
Case 1
;I do not think this is needed
EndSelect
If $NetworkID
If IsInSubnet($IPAddress,$NetworkID+'/'+$Mask)
For Each $Key In Split(ReadProfileString("PathTo\Printers.ini",$Section,""),Chr(10))
If $Key
;? ReadProfileString("PathTo\Printers.ini",$Section,$Key)
If NOT PriMapState(ReadProfileString("PathTo\Printers.ini",$Section,$Key))
If NOT AddPrinterConnection(ReadProfileString("PathTo\Printers.ini",$Section,$Key))
$Error = @ERROR
EndIf
EndIf
EndIf
Next
Dim $Index, $KeyName
$Index = -1
Do
$Index = $Index + 1
$KeyName = EnumKey("HKEY_LOCAL_MACHINE\System\CurrentControlset\Control\Print\Printers\",$Index)
If NOT Left($KeyName,2) = ",,"
If Left(ReadValue("HKEY_LOCAL_MACHINE\System\CurrentControlset\Control\Print\Printers\" +
$KeyName + "\DsSpooler\","portName"),3) = "LPT" OR
Left(ReadValue("HKEY_LOCAL_MACHINE\System\CurrentControlset\Control\Print\Printers\" +
$KeyName + "\DsSpooler\","portName"),3) = "USB"
Exit $Error
EndIf
EndIf
Until NOT $KeyName
;? ReadProfileString("PathTo\Printers.ini",$Section,"DefaultPrinter")
If NOT SetDefaultPrinter(ReadProfileString("PathTo\Printers.ini",$Section,"DefaultPrinter"))
$Error = @ERROR
EndIf
Exit $Error
Else
;Maybe IsInSubnet() has returned "false" and has thrown an error
If @ERROR
$Error = @ERROR
EndIf
EndIf
EndIf
Next
EndFunction

The INI File
[10.17.1.32,255.255.255.224]
DefaultPrinter=\\Server\Printer1
ColorPrinter=\\Server\Printer2
Fax1=\\Server\Printer3

[10.17.1.64/255.255.255.224]
DefaultPrinter=\\Server\Printer4
ColorPrinter=\\Server\Printer5
Fax1=\\Server\Printer6

[10.17.1.96/27]
DefaultPrinter=\\Server\Printer7
ColorPrinter=\\Server\Printer8
Fax1=\\Server\Printer9


Witto
(MM club member)
2006-08-27 03:17 AM
Re: Yet another printer script

Well Doc, thanks for your reply. I was waiting for this kind of reaction. I was just wondering if this kind of script was possible and if it was done somewhere.
I don't think either there are many networks split up in subnets like presumed in this script. P.e. a subnet for the commercial dep, a subnet for the accounting dep., a network for engineering dep. etc.
Most of the time or always, al theze departements will just be part of one bigger network, p.e. 192.168.0.0/24. If you have 150 or 200 workstations in a network like this, it is very unlikely that all these users use the same printer configuration or the same default printer.
But presume you had the opportunity to reorganise the network and divide it into smaller subnets (mask /27 or so). Would it be a silly idea doing this?


NTDOCAdministrator
(KiX Master)
2006-08-27 04:34 AM
Re: Yet another printer script

Who's to say. What doesn't work for me may work for you just fine or visa-versa.

However, let's say this was an all new network / Company and they just plopped down 1,000 machines. Well that is not automated either so one would assume whoever installed/setup the workstation would at least connect one printer for the user.

Or if not, if they could write down on a piece of paper the names of the computer and the location and you could then know that say printers x-y-z belong to this area and just write an .ini that had computer name and printer and be done with it.

All in all if this suites you well that cool too. Just guessing that you now have 8+ hours into this project for what I think most users "shouldn't" need as they should already have a printer installed.

But let's say you did have your network managed at little segments well that has pros and cons as well. The more you have in little groups the more you have in back-end management for yourself too. DHCP scopes, DNS records, Printer Scripts, etc...

Bottom line, if you're happy that's what really counts because none of us work where you do.

We had 400+ printers on 2 print servers before that served up to about 3,000 users and we also
had multiple subnets but as you say that was sort of the problem too in that if you just
assumed subnet x, it might be too far from the user and he/she would want a different one.

Just too dang easy to connect to a printer for a user so never tried to spend time automating it.

C:\ START \\PRINTERSERVER1 or START \\PRINTERSERVER2
Right Click CONNECT to any printer you want.

All printer shares match the names of the labels on all printers
so not too difficult for even a noob to do.


mewright
(Lurker)
2006-08-27 10:26 PM
Re: Yet another printer script

Am I missing something.

All our printers are named in such a way that any user can figure out where the nearest printer is located - 500+ printers, 12 offices around the state, most are multiple story buildings. The user uses the search function to look for the nearest AD printer. A double-click and all is done.


NTDOCAdministrator
(KiX Master)
2006-08-27 10:32 PM
Re: Yet another printer script

Quote:

The user uses the search function to look for the nearest AD printer




Well you can use the search feature in AD but I'll bet you I can install 10 printers by using DOS console in the time it takes you to install 1 printer using AD search.

But as you say most users that have not been taught will go the slow route too.

This script is an attempt to make it so that NO user intervention is required anywhere on his network for mapping a printer.