Link to home
Start Free TrialLog in
Avatar of GATOR420
GATOR420

asked on

The *ultimate* printer mapping script challenge

Dear Respected Colleagues,

I know what I want, but I have no idea how to do it. I am calling upon the wealth of knowledge that this community has to offer to create what I would call the Ultimate Map Printer Script.

My requirements:
I need to come up with a script that can map printers based on the login location of an end user. Example, if a user logs in at the New York site on the 3rd floor, they will automatically be mapped to a printer nearby their location and set as default if they don't have any printers currently set up. If they do have an existing printer (like a local printer) I need that to stay as default, just adding the others as secondaries. If they fly to Boston the next day and log on at the Boston site on the 7th floor, I need the same script to map them to a printer nearby them on the 7th floor.

Possible options of configuraions is unlimited, printer goups, computer groups, user groups... Whatever configuration it would take to make something like this work.

Is this even possible? I would think it could be if enough variables were filled in, but I would have the faintest idea of how to engineer it properly. Thanks in advance for even considering this.
Avatar of Fatal_Exception
Fatal_Exception
Flag of United States of America image

I would suggest you put this question in either the windows server section (2003) or in the scripting section.  You will get far more help there than in this thread...  just a thought..  :)

FE
Avatar of GATOR420
GATOR420

ASKER

I was trying to find the right section to put this in, but since it may also involve the setting up of groups, users, printers, etc.. I wasn't sure. I looked for a "scripting" section, I couldn't find it. Where is that located under?
It's actiually not too difficult.
The first thing you need to do is establish a method of determining where the user is physically located. There are two options here:
Get the logon server to set a variable, assuming that each location has it's own logon server.
Get the subnet information from the PC and use this to determine the location (assuming DHCP is used).

How many different locations do you have?
How many printers do you have?
What types of printers do you have?
Is there a print server at each location?

I would expect that you will have some truouble determining which printer to use as the default for any given location. Yiou would need to find a way of deciding this beforehand for locations that have multiple printers.

Other questions I will need answered:

What operating systems are the workstations running?
How are the printers assigned IP addresses?
What is the network setup, ie. distribution and configuration of subnets, routing, helper addresses, restrictions etc.?
How advanced is the current logon script process?

How confident are you that your support team will be able to manage complex scripts?
1. Each location does have it's own logon server.
2. DHCP is being used.
3. 2 locations right now, but will be going to 3 soon.
4. Probably between around 100-150 network printers
5. A few types of printers, but HP mostly. Ideally, I would like to map each user to 1 color printer and 2 black and white printers with one of the black and white printers being their default if they don't already have a local printer installed.
6. There is a print server at each location.
7. The default should be local printer if one is installed, then black and white network printer as default if no local printer is installed, with a back up black and white and a color printer.
8. Windows 2000 & XP are the operating systems being used.
9. Printers have static reserved IP addresses on seperate VLANs.
10. Floors are split into A and B sides, with a subnet for each side.
11. The current logon script process is very simple, just maps a few network drives.

I am pretty confident that I will be able to manage it as long as I know what each section does. I am very comfortable with DOS scripting but something like this is a bit out of my league for DOS scripting. If it's in VBS or WSH I have very limited basic knowledge but catch on quickly. :)
OK, it sounds like your setup might make things relatively easy.

You will have to define your subnets somewhere. I would assume that each side of each floor has a printer that could be used as primary and secondary printers. Is there a colour printer on each floor too?

You need to build an association of each subnet with a list of printers. There are a couple of ways of doing this:
1 - Build a text file for each subnet that contains a list of printer queue names and designations.
2 - Name the printers with subnet and designation information.

Either way, you will have to define a procedure for adding and managing printers.

To get us started, lets capture the current subnet:

I'll assume that we are working with class c subnets here. There might also be workstations that have more than one interface, so I have to assume that only one interface will be configured to be on the subnet at the time of login.
Substitute the 192.168 with your own network settings.

for /f "tokens=2 delims=:" %%a in ('ipconfig^|find "192.168"^|find /i "ip address"') do for /f "tokens=1-4 delims=." %%b in ("%%a") do set subnet=%%b.%%c.%%d.0

This will set the variable SUBNET to 192.168.X.0 where X is dependent on the location.

If we had a file named 192.168.X.0.txt in the logon share containing the printer information then we could do:

for /f "tokens=1-3 delims=      " %%a in (!subnet!.txt) do (
if %%c == "default" (
      RUNDLL32 PRINTUI.DLL,PrintUIEntry /in /y /n\\%%a\%%b
) else RUNDLL32 PRINTUI.DLL,PrintUIEntry /in /n\\%%a\%%b

The contents of the 192.168.X.0.txt file would be something like:

SERVER1      printername1      default
SERVER1      printername2      secondary
SERVER1      printername3      colour

Please note that I am using TAB as the delimeter.

You would need to manage these files properly to ensure that the details are always correct, updating them when changes occur.

For the time being, this ignores the local printer. Lets first make sure that this will work as required. If this were to go into a seperate batch file it would look something like this:
::--------------------------------------------------------------
@echo off
setlocal ENABLEDELAYEDEXPANSION

for /f "tokens=2 delims=:" %%a in ('ipconfig^|find "192.168"^|find /i "ip address"') do for /f "tokens=1-4 delims=." %%b in ("%%a") do set subnet=%%b.%%c.%%d.0

for /f "tokens=1-3 delims=      " %%a in (!subnet!.txt) do (
if %%c == "default" (
      RUNDLL32 PRINTUI.DLL,PrintUIEntry /in /y /n\\%%a\%%b
) else RUNDLL32 PRINTUI.DLL,PrintUIEntry /in /n\\%%a\%%b
::--------------------------------------------------------------

You should test this and see how it goes.
Please let me know if I am going down the wrong road with this.

On second thought, the /y doesn't work as expected, it'll have to be:

if "%%c" == "default" (
      RUNDLL32 PRINTUI.DLL,PrintUIEntry /in /n\\%%a\%%b
      RUNDLL32 PRINTUI.DLL,PrintUIEntry /y /n\\%%a\%%b
) else RUNDLL32 PRINTUI.DLL,PrintUIEntry /in /n\\%%a\%%b
Great scripts... sorry didnt make it in time....
:)

Cyber
I think this is exactly along the lines of what I am looking for here. There may be some details that change as I test this script and see how it works. I'm relatively new to managing this company's network and may not have all the details 100% accurate. Being as it is the weekend, I won't be able to test until Monday at the earliest. I'm very excited with the potential possibilities though!

So let me try to rexplain it to you as how I think it works just so I understand it.

It checks their current subnet at time of log in
It matches that with a text file of the same name as the subnet  that contains the printers I would want them to be mapped to?
It ignores the default printer if one is installed and just installs the printers located in the text file.

Is that about right?

Does this also actually set the default printer to default status on the workstation?

I can't begin to thank you enough if this all works the way I hope it will...
Absolutely..  very good LittleRed..  Gotta love scripting gurus..  :)
You ain't seen nothin' yet Fatal_Exception!

Sounds about right GATOR420.

The difficult part at the moment is figuring out whether the user has a local printer installed. This is made worse by the possibility of  USB printers and virtual devices like Acrobat Distiller.
One way to do this would be to delete all network printers and then list what's left. I can't think what might be the best way to do this (it's late and I can't think straight) but this should work:

for /f "tokens=3 delims= " %%a in ('cscript %systemroot%\system32\prnmngr.vbs -l^|find /i "printer name"^|find "\\"') do RUNDLL32 PRINTUI.DLL,PrintUIEntry /dn%%a
for /f %%a in ('cscript %systemroot%\system32\prnmngr.vbs -l') do find "LPT1"&& set localprinter=yes

This will delete all network printers and then set the variable localprinter to yes if the cscript output in the second command contains LPT1 anywhere ie. if there is a printer defined that uses the local printer port. This might need to be adjusted or added to for other possibilities, but it'll do as a starting point

Please forgive the cscript, I'm not too keen on having to rely on it. I am also testing this on an XP Pro machine at the moment, it will have to be tested on 2000 too.

It's also worth noting at this point that the invocation of PRINTUI.DLL can take a little time. Furthermore the command completes immediately, so it might be difficult to set the default using this method since the installation of the printer might only take place several seconds after we make it the default. I also don't know yet how it will react when involked multiple times. If these cause us problems we will have to look at other ways of doing the same things.

Good luck with your testing.
I've given it a bit more thought and had a play with it today. I have to say that RUNDLL is not working for me. There are also some other things:

The prnmngr.vbs cscript will  tell you what your current default printer is, which you can pass through FIND looking for \\. This tells you if your default printer is a network printer or not. If it is then change the default to the specified local printer.

The prnmngr.vbs cscript also adds printers faster and more transparently.

There are also a number of different ways to define which printers get mapped where. This can also be expanded to include subgroups on a per user or per group basis if needed. The file containing the printers is just one, fairly simple way. Another way is to include the subnet and designation info in the printer name. This way you can list the printers on the local print server using net view \\printserver|find "Print". You would have to find a way of defining the print server name if it's not the logon server, but this shouldn't be too difficult. I have used this method in the example below.
There is another way which is perhaps more complicated, but has it's merits, using active directory object information extracted using LDAP. You may have to add to the object properties, but most of the required printer information is already there.

One of the drawbacks of the cscript however, is it's output format. If we really wanted to, we could alter the vbs script to give us a tab delimeted format instead. If we did this, we could do much the same thing as using active directory, but define the subnet and designation in the location and comments fields of the printer properties. These are included in the printer details provided by the cscript.

Having played a bit, I found that changing the printer names seems to work quite well. I changed the printer 'descriptive' names to 'Subnet Designation - Name'. For example '163 Default - HP Color LaserJet 4550'. 163 is the subnet (derived from the third part of the network - X.X.163.X or class c subnet), Default is the designation and the rest is the actual description. The script looks like this:

::--------------------------------------------------------------------------
@echo off
setlocal ENABLEDELAYEDEXPANSION

:: Set the printer server name (just for now, this will need to be dynamic in practice)
set printserver=pserver1

:: Get subnet info using ipconfig
for /f "tokens=2 delims=:" %%a in ('ipconfig^|find "192.168"^|find /i "ip address"') do for /f "tokens=1-4 delims=." %%b in ("%%a") do set subnet=%%d
echo Currently on subnet !subnet!

:: Find local default printer, if any
cscript %systemroot%\system32\prnmngr.vbs -g|find "\\"||set localprinter=yes
if "!localprinter!" == "yes" echo Default printer is local

:: List printers on local server and map them
for /f "tokens=1,3,4*" %%a in ('net view \\!printserver!^|find /i "print"') do (
      if "%%b" == "!subnet!" (
            cscript %systemroot%\system32\prnmngr.vbs -ac -p "\\!printserver!\%%a"
            if "%%c" == "Default" if not "!localprinter!" == "yes" for /f "tokens=3 delims=\" %%n in ('cscript %systemroot%\system32\prnmngr.vbs -l^|find /i "!subnet! Default"') do cscript %systemroot%\system32\prnmngr.vbs -t -p "\\!printserver!\%%n"
      )
)
::--------------------------------------------------------------------------

Modify to suit your network and server parameters and give it a try. If you don't want to try the printer name changes, just work the file method into the last section of the script.

Sorry if I'm babbling on a bit, but this is quite an interesting one.
Nope, this is great stuff! Not sure I understand everything in that last post but I'll have to take some time and sort it out in a bit. Bear with me though, today might not be my ideal day for testing as we have a few people out on vacation this week it's going to be pretty hectic.
ASKER CERTIFIED SOLUTION
Avatar of LittleRed1
LittleRed1

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Very nice Red..  I am going to ck it out on my test box also...   A job well done..

FE
Opps! I forgot.

Sorry about the href, first link post.

To define the location and designation of the of the printers, simply place the subnet in the Location property of your printer and the designation in the Comments section. These two are seldomly used and are reported in the modified cscript.

Fantastic stuff! I am still too tied down to test it out here at the moment, but I can't wait to try it! Feel free to post any other upgrades to it while I'm trying to catch up :)
OK... One little kink to throw in the works... The subnet is a 255.255.252.0 subnet and multiple printers across the subnet making it very hard to narrow down and pinpoint where users are and where their nearest printer is...  Any ideas of how we can work around that?
I'm sure that there will be a way. It's probably a good idea to get a good understanding of your network design.

A couple of things I can think of right now:

It's possible that each location has a separate router, and consequently each location will have a different default gateway.

We could have a closer look at the IP address and try to find a per location factor, for example, if each location had the 8th number in the IP address different, we could use that.

Have a look at your DHCP scopes, see if that might help us.

If threre's anything else you can think of, just let me know.
I haven't forgotten about this, still trying to gather information for this. Time has just been short lately. I appreciate the patience... :)
Still haven't forgotten about this, time just seems to be a commodity I don't have much of anymore. I do plan on swinging back around to this again soon. Please do be patient with me. :)
Still haven't forgot about this, just due to the projects on my plate and their priority I haven't had a chance to check this out. Still worth the points in effort. Thanks again. Hopefully I will be able to revisit this again sometime in the near future.