Share:


WMI Printer Classes and Writing to a Log File

Hey, Scripting Guy! Question Hey, Scripting Guy! I am new to scripting and love the power and flexibility scripting gives me. I am writing—or rather, trying to write—a login script that will audit users' printers and write the details to a log file named with their user name. My problem is retrieving printer properties from two different WMI classes, W32_Printer and W32_PrinterDriver, for each printer. I have almost got it; however the script only writes the last printer out. I understand how to write to a text file, but how do I write information from all printers to the text file?

GetPrinterForUser-BadOutPut.vbs

on error resume next
Set WshNetwork = WScript.CreateObject("WScript.Network")
strComputerName = WshNetwork.ComputerName
strUsername = WshNetwork.UserName
strDomainName = WshNetwork.UserDomain
Set myFSO = CreateObject("Scripting.FileSystemObject")
Set myFile = myFSO.CreateTextFile("c:\temp\scripts\" & strUserName & ".csv",1)
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputerName & "\root\cimv2")
Set colInstalledPrinters =  objWMIService.ExecQuery _
    ("SELECT * FROM Win32_Printer")
myfile.writeline "DomainName" & "," & " ComputerName" & "," & " UserName" & "," & " PrinterName" & "," & " NetworkPrinter" & "," & " PortName" & "," & " DriverName" & "," & " Driver"
For Each objPrinter in colInstalledPrinters
                strPrinterinfo = strDomainName & "," & strComputerName & "," & strUserName & "," & objPrinter.Name & "," & objPrinter.Network & "," & objPrinter.PortName & "," & objPrinter.DriverName
Next
Set colInstalledPrintersDriver =  objWMIService.ExecQuery _
    ("SELECT * FROM Win32_PrinterDriver")
'For Each objPrinterDriver in colInstalledPrintersDriver
'               strPrinterinfo2 =  strPrinterinfo & "," & objPrinterDriver.Version
'Next
myfile.writeline strprinterinfo

-- GM

Hey, Scripting Guy! Answer Hello GM,

You have hit upon a common problem that is faced by all scripters at one point or another. One thing you can do is move your writeline command up inside your For…Each…Next loop. As your script is currently written, you are looping through everything, collecting all your printer information, and then when you exit the loops, you are writing to the text file. The value of your strprinterinfo variable is getting overwritten each time you walk through the loop. When you have completed the looping process, there is only one value left assigned to the strprinterinfo variable—the value associated with the last printer.

Let’s demonstrate what you are currently doing. In the VBScript code seen below, an array named ary is created and is assigned the value of five numbers. The For…Each…Next loop is used to walk through the array and the variable i is used to keep track of an individual element from the array. Each time through the loop, the value of the myvalue variable will change. After you are finished looping through the array, the value of the myvalue variable is displayed by using the Wscript.Echo command. This code is seen here:

ary = Array(1,2,3,4,5)

For each i In ary

myValue =  i

Next

WScript.Echo "Outside the loop " & myValue

When you run the above script, "Outside the loop 5" is displayed:

clip_image001


If you move the Wscript.Echo command inside the For…Each…Next loop, you will be able to pick up the value of the myValue variable as it changes with each iteration of the loop. This is seen here:

ary = Array(1,2,3,4,5)

For Each i In ary

myValue =  i

WScript.Echo "Inside the loop " & myValue

Next

When the above code is run, the "Inside the loop" string is displayed five times with the value of the myValue variable. This is seen here:

Inside the loop 1
Inside the loop 2
Inside the loop 3
Inside the loop 4
Inside the loop 5

This works, but is a bit inefficient. If you have a lot of data, each of the write operations is generating a File IO operation, which as you probably know is terribly slow! So what you can do is collect the information in a variable inside the loop, and then make a single IO to disk. This is illustrated here:

ary = Array(1,2,3,4,5)

For Each i In ary

myValue = myValue & VbCrLf & i

Next

WScript.Echo "Single IO " & myValue

When the code above is run, the following results are displayed. Instead of making five or six different input/output operations, only a single output is made:

clip_image002




Can I Write Scripts with Different User Credentials?

Hey, Scripting Guy! Question Hey, Scripting Guy! I just downloaded and started to use Scriptomatic 2.0. Nice piece of work. But I need to be able to write scripts with different user credentials. Any way of doing this?

-- AO

Hey, Scripting Guy! Answer Hello AO,

It is easy to use alternate credentials using Windows PowerShell because there is the –credential parameter for the Get-WmiObject cmdlet. To query the BIOS on a remote computer, you would use a command such as the one seen here:

Get-wmiobject –class WIN32_bios –comptuer berlin –credential nwtraders\administrator

That is it. It pops up a dialog box for the user to type the password:

clip_image003


If you would like information about getting started using Windows PowerShell, you can find it on the Script Center.

Using VBScript, you will need to use the SwbemLocator object and use the connectserver method, which is documented on MSDN. It is also talked about on the Script Center. We also have a Hey, Scripting Guy! Blog post that talks about this process.

The scripts that are created by the Scriptomatic 2.0 do not allow the use of credentials. This is because they use the SwbemServices object and the ExecQuery method. This object is talked about on MSDN.



Is the Win32_WindowsProductActivation Class Available in Windows Vista?

Hey, Scripting Guy! Question Hey, Scripting Guy! Has the Win32_WindowsProductActivation class been removed from Windows Vista? I have a script that I use to activate Windows, but that script no longer works on Windows Vista.

-- HM

Hey, Scripting Guy! Answer Hello HM,

The Win32_WindowsProductActivation class has been removed from Windows Vista. Instead, you need to use these two classes seen here:

SoftwareLicensingService

SoftwareLicensingProduct

Both WMI classes are found in the Root\Cimv2 WMI namespace.



Can I Use an Event Query to Capture Information About Dropped IP Packages from Windows Firewall?

Hey, Scripting Guy! Question Hey, Scripting Guy! I have searched the Internet and haven't found an answer yet, so I decided to try to ask you experts: Is there a way to use an event query to capture information about dropped IP packages from the Windows firewall?"

Thanks in advance and kind regards, and eagerly awaiting the Scripting Games for next year.

-- WK

Hey, Scripting Guy! AnswerHello WK,

No there is no way to script using a WMI event query to capture information about dropped IP packets from the Windows firewall. Even if you could do this, you would receive so many event notifications as to make the information practically useless. The reason you cannot get a WMI query to produce the events is that there is no WMI class that provides this information.

You could do an event modification query for the log file itself; however, there are many items logged to the log file and as a result you would not know what was triggering the event. If you configure the firewall to only record dropped packets, you could achieve what you desire. 
 


What Can I Do About a Repeated "Script Error" in My Browser?

Hey, Scripting Guy! Question Hey, Scripting Guy! Like so many others, I notice I'm going nuts with this "script error" message in my browser. I've had it! Please tell me how to stop it completely. I don't want to have to click anything every time it happens. It is so annoying! Any suggestions?

-- UW

Hey, Scripting Guy! Answer Hello UW,

I am sorry you are getting a “script error” in your browser. The error you are getting is not related to either your browser or to anything you are doing. Rather, it is a problem with the Web site you are going to. There are many kinds of scripts that are used on Web sites, such as try to detect your screen resolution to resize the page or your version of operating system to adjust the information they present. Then they may simply have a script that takes information from a form you fill out and submits that information to a database to retrieve information for things like telling you if a particular kind of item is in stock.

The only way to stop the error completely is to contact the person who runs the Web site to get the web page updated. It is interesting that you are receiving this error on a regular basis because I seldom get the error. I am currently running Internet Explorer 8 on Windows 7. It may be that upgrading your browser will help solve your problem, but diagnosing user problems via eail is a bit like being a dentist and trying to pull a tooth from across the country, which is an iffy proposition at best.

We come to the end of another Quick-Hits Friday. To see what we will be talking about next week, follow us on Twitter or Facebook. If you have any questions, shoot us an e-mail at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you next week.


Ed Wilson and Craig Liebendorfer, Scripting Guys