How Can I List the Network Printers For the Logged-On User?

How Can I List the Network Printers For the Logged-On User?

  • Comments 6
  • Likes
Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I create a logon script that lists the network printers for the logged-on user, then writes that information to a text file?

-- RC

SpacerHey, Scripting Guy! AnswerScript Center

Hey, RC. You know, the nice thing about coming to work after a few days off is – well, OK, so maybe we can’t actually think of anything nice about coming to work after a few days off. If you happen to work at Microsoft, however, you’re at least likely to hear something interesting the moment you get back. For example, this morning the Scripting Guy who writes this column was in the bathroom when he overheard the following conversation:

“So how did he get a window office?”

“I had to give him a window office. He told me he gets violent and angry if he doesn’t have a window office. I didn’t want him to get violent and angry, so I gave him a window office.”

Needless to say, window offices are more valuable than gold around here; for the most part they’re only awarded to the best and the brightest. (And, for some reason, to the Scripting Editor, who also has a window office.) As you might expect, the Scripting Guy who writes this column doesn’t have a window office. Of course, up until now, he wouldn’t expect to have a window office; after all, his name rarely comes up any time people talk about the best and the brightest. But apparently you don’t have to be among the best and the brightest, at least not as long as you’re willing to be violent and angry. Hmmm ….

Ah, who are we trying to kid? For one thing, the Scripting Guy who writes this column is too lazy to be violent. For another, how could he ever be angry, especially when he has the opportunity to do things like write a logon script that can list all the network printers for the logged-on user:

Const ForWriting = 2

Set objNetwork = CreateObject("Wscript.Network")

strName = objNetwork.UserName
strDomain = objNetwork.UserDomain
strUser = strDomain & "\" & strName

strText = strUser & vbCrLf

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colPrinters = objWMIService.ExecQuery _
    ("Select * From Win32_Printer Where Local = FALSE")

For Each objPrinter in colPrinters
    strText = strText & objPrinter.Name & vbCrLf
Next

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFile = objFSO.CreateTextFile _
    ("C:\Scripts\Printers.txt", ForWriting, True)

objFile.Write strText

objFile.Close

Two quick caveats before we explain how the script works. First, in its current incarnation this script won’t work on Windows 2000 or any earlier versions of Windows; that’s because those flavors of Windows don’t include the Local property as part of the WMI class Win32_Printer. But don’t get violent and angry; before we call it a day we’ll show you a modified script that will work on Windows 2000.

Second, this script simply logs the information to a text file named C:\Scripts\Printers.txt; each time the script runs it overwrites the information in Printers.txt with the most recent collection of printer information. That’s fine, but it might not be the behavior you had in mind. If that’s the case then you’ll have to modify the code that writes to the text file. But, again, there’s no need to get violent and angry (violent or angry, maybe, but not violent and angry). After all, we have plenty of information about working with text files. (And that doesn’t even include the Microsoft Windows 2000 Scripting Guide, which also has information about working with text files.)

OK, now we’ll explain how the script works. To begin with, with define a constant named ForWriting and set the value to 2; we’ll use this constant when we write the printer information to the text file. Following that we create an instance of the Wscript.Network object, then execute these three lines of code:

strName = objNetwork.UserName
strDomain = objNetwork.UserDomain
strUser = strDomain & "\" & strName

What are we doing here? Well, all we’re doing is determining the name of the logged-on user (using the UserName property) and the domain of the logged-on user (UserDomain); that’s what the first two lines of code are for. In line three we simply concatenate the user name and domain, giving us a user name in the format DOMAIN\username. In other words:

FABRIKAM\kenmyer

We then take this information plus a carriage return-linefeed (using the VBScript constant vbCrLf) and stash it in a variable named strText:

strText = strUser & vbCrLf

After that we connect to the WMI service on the local computer (because this is a logon script we don’t care about connecting to the WMI service on a remote computer). We then use this line of code to retrieve a collection of all the network printers on the computer:

Set colPrinters = objWMIService.ExecQuery _
    ("Select * From Win32_Printer Where Local = FALSE")

Here we’re simply selecting all the instances of the Win32_Printer class, or at least those instances where the Local property is False. As you can probably guess, that results in a collection of all the network printers; if the Local property was True we’d have a local printer rather than a network printer. That’s why the script won’t work on Windows 2000; the Win32_Printer class in Windows 2000 doesn’t support the Local property.

But don’t worry: we said we’d show you an alternate script that will work on Windows 2000 and, by golly, we’re going to do just that.

But not yet. Before we do that, let’s finish explaining how the original script works. After we retrieve the printer information we set up a For Each loop that lets us walk through the entire collection; for each printer in the collection we use this line of code to add the Name of the printer to the variable strText:

strText = strText & objPrinter.Name & vbCrLf

This should be pretty easy to follow: all we’re doing is assigning a new value to strText. And just what is that new value? That’s easy: it’s the existing value of strText plus the name of the printer plus a carriage return-linefeed.

The rest is easy. First we create an instance of the Scripting.FileSystemObject object; we then use the CreateTextFile method to create a new text file named C:\Scripts\Printers.txt:

Set objFile = objFSO.CreateTextFile _
    ("C:\Scripts\Printers.txt", ForWriting, True)

Note the three parameters we pass to the CreateTextFile method:

The full path to the new file (C:\Scripts\Printers.txt).

The constant ForWriting, which indicates that we want to write to the file.

The value True, which tells the script to overwrite an existing instance of C:\Scripts\Printers.txt. If the file Printers.txt exists then the script will overwrite it; if the file doesn’t exist then the script will create it.

After that we call the Write method to write the printer information to the file, then use the Close method to close the file. If we open the text file we should see information similar to this:

FABRIKAM\kenmyer
\\atl-ps-01\b43-2927-a
\\atl-ps-01.fabrikam.com\b43-2315-a
\\atl-ps-02\HP LaserJet 5MP

Which is exactly what we wanted to see.

Now, what about Windows 2000? Well, without explaining how this works, here’s a logon script that will run on Windows 2000 and Windows NT:

Const ForWriting = 2

strComputer = "."

Set objNetwork = CreateObject("Wscript.Network")

strName = objNetwork.UserName
strDomain = objNetwork.UserDomain
strUser = strDomain & "\" & strName

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

strText = strUser & vbCrLf

Set colPrinters = objWMIService.ExecQuery("Select * From Win32_Printer")

For Each objPrinter in colPrinters
    If Not objPrinter.Attributes And 64 Then 
        strText = strText & objPrinter.Name & vbCrLf
    End If
Next

Set objFSO = CreateObject("Scripting.FileSystemObject")

Set objFile = objFSO.CreateTextFile _
    ("C:\Scripts\Printers.txt", ForWriting, True)

objFile.Write strText

objFile.Close

The big difference here? This time we need to return all the printers, both local and network. We then check the value of the bitmask property Attributes. If the “switch” equal to 64 is on then this is a local printer; if it’s not, then this must be a network printer. In that case, we then add the Name of the printer to the variable strText.

Incidentally, we need to issue a correction before we go. Earlier we stated that window offices were distributed to “the best and the brightest.” As it turns out, window offices are distributed on the basis of seniority. In other words, the Scripting Editor didn’t get a window office because she’s really, really smart; instead, she got one because she’s really, really old.

Just don’t tell her we said that.

Editor’s Note: The fact that the Scripting Guy who writes this column is much older than the Scripting Editor sort of blows away that last theory. Unless we’re talking about mental age, in which case the Scripting Editor has at least managed to reach adulthood, unlike the Scripting Guy who writes this column.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • For some unknown reason, when you have a remote printer on your computer and this remote printer is no longer existing on the remote server, you won't see that printer on the Win32_Printer query

  • That script is all fine and good assuming you have logged onto every single one of your computers. In testing, ran script against local computer, works good. Ran script against a computer in my domain that I have never logged into but I know has mapped printers, no output. Login to remote computer using the same cred's I'm running the script as, works good.

    How exactly can you retrieve a list of mapped printers from all computers in a Domain, regardless of who has logged in?

  • Hello, I am hoping to integrate this script in to a profile migration script I am custom building. I like the way the script works. However, how can I make it so it only lists the printers in the TXT file and not the current users info? I attempted this, but it leaves the first line in the text file blank. This takes me to my next question. How can i reverse the process? I would like to be able to use a script to later install the printer listed in the txt file to another XP PC when restoring a users backed up profile.

    Thanks,

    SConnett

  • Can we please leave out the humor and just get to the part that describes and explains the script? it's real annoying, always having to read a couple paragraphs of jokes before getting to the parts that matter. There are plenty of joke sites out there, if we wanted jokes, we'd go to them. People search for scripts when they find your site, not jokes.

  • Thank you for the light hearted style that you put in your blog entries. Reading knowledgebase entries can become monotonous, so reading something with a human feel as well as useful information is nice. Some others obviously don't realize this is a BLOG, therefore it's up to the author how they chose to post. In MY opinion, reading a few minutes to save you hours of work is a small price to pay for free scripting information... and humor thrown in is the icing on the cake.

    Cheers!

  • Hi,

    I tested your script and it work fine... locally ! But do you known how can we could use this script to determine network printer on a remote computer running in the actual running session ?

    Exemple: I would like to known which network printers are in the session of my end-user named Domain\Thomas on the computer PC001, from a script started from my technician computer PC002 in my Windows session Domain\Admin.

    I tested the WMI request with = FALSE and it seem to be not valid when started in remote location. I don't known if this option is a limitation by WMI or the impersonate request is not formulated correctly...

    Please find a solution, this could be very useful to diagnose remote computers without having to do a remote GUI connection (RDP, DameWare, VNC) and stop user work.