The VBScript Network and Systems Administrator's Cafe:

March, 2008

Mar 27 2008   3:03PM GMT

Rebooting or Shuttingdown a Server Remotely with VBScript



Posted by: Jerry Lees
Windows Administration, Remote management, Functions, Development, VBScript, Subroutines

In this installment I’d like to share with you a scriplet I developed out of frustration with not having found this information anywhere else.

 On occasion you need to reboot a server, sure you can do it by logging in or by the shutdown command on windows XP. Heck you can even do it with the Windows 32 API calls in C++! However, sometimes you don’t want to be up and awake when you need to reboot a server. Plus, you might want to have some sort of logic behind it like instead of rebooting every night blindly you might want to check to see is a process is running (like a windows service) and stop it in a controlled manner before rebooting the system– we’ve all go those one off servers that have some weird application that needs fiddling with before you reboot, or atleast the lore at the office says you need to do something first. Right?

Well, I recently had such a situation and became frustrated that I couldn’t reboot a server cleanly with in a script without first executing from within the script, as a child process, a batch file to do the reboot for me. Sure it works… and the main reason I didn’t like it was it wasn’t as sophisticated as I’d like. But another problem is that I would have no real way of knowing what the outcome of the reboot process– in other words, I wouldn’t be able to handle the fact that the reboot didn’t occur or the batch file had an error because windows would have returned only that the command prompt executed and the batch was ran.

In two previous posts, I’ve provided information on Functions, WMI, and Methods to lead up to this topic. If you missed them you might go back and read the quickly so you’ll be up to speed. The posts are:

Working with Subroutines and Functions in VBScript
Using Windows Management Interface (WMI) to Make Your Life Easy.

 In the following script, I create a function called Reboot that uses WMI to create a connection to a server name you pass to it (Note: to protect you I have set the call to reboot() in the script to use “.”, which is the local machine. Change “.” to “ServerName” to reboot a specific remote machine. In other words… run this code unchanged and your desktop will reboot in the next 30 seconds.)

Reboot(”.”)

Function Reboot(StrSrv)
   Set objWMIService = GetObject(_
   ”winmgmts:{impersonationLevel=impersonate,authenticationLevel=Pkt,(Shutdown)}!\\”_
   
& StrSrv & “\root\cimv2″)
   Set colItems = objWMIService.ExecQuery(”Select * from Win32_OperatingSystem”,,48)
   For Each objItem In colItems
        WScript.Echo objitem.Reboot
   Next
End Function

This is a really useful scriptl function, when combined with other pieces of code to gather performance monitor counters (later I’ll post some code examples on this) you could reboot a server if the non-paged pool memory reaches a point where the system is probably going to lock up due to a leaky app or driver… this was my issue I solved with vbscript. 

Again, this code works perfectly. However, sometimes the formatting of the blog breaks the code if you copy and paste it into your editor. So, if you’d like to not type or troubleshoot any syntax errors due to the copy and paste problems I’ve provided the code for download for you. From here on out I will make the code available for download from my website’s (www.webstemsadministration.com) File Depot under the ITKE Blog Scripts category.

Enjoy and happy scripting!

Extra credit: Can you figure out what the following part of the code does?{impersonationLevel=impersonate,authenticationLevel=Pkt,(Shutdown)}

Mar 24 2008   3:03PM GMT

Found discount: 50% off Kaspersky Antivirus Products



Posted by: Jerry Lees
Antivirus

I don’t normally think enough about a product to pass these things on, or the discount isn’t real enough to warrant my bugging you with the information– but I recently found a link to Kaspersky Anti-Virus Products where they are offering almost 50% off your entire purchase of their antivirus products.

Thier products are pretty good, offering both home and business Antivirus solutions, and they are inexpensive enough to warrant a look if your in the market for antivirus software.

As I understand it, the offer is until March 31st and you enter the code 50KMS into the cart on checkout and the cost of the order is cut in about half. That’s substantial. When I tried it, the code wasn’t needed it looked like it was already discounted through the link I found above when I compared the shown prices with the website’s prices.

 Essentially, it ended up being $39.95 for a year of their latest antivirus application and only $20 for their newest mobil security product for smartphones and PDAs.

If your in the market for antivirus software– or looking to upgrade your current version of their product you might check it out.


Mar 21 2008   5:39PM GMT

Explanation: Using Microsoft.XMLDOM to work with data feeds in VBScript



Posted by: Jerry Lees
Development, Microsoft.XMLDOM, XML, 360voice, VBScript, DataManagement

You may recall we recently worked with a cool little script that itself didn’t have anything to do with systems administration, the 360voice API script in a previous post, but the concepts can be used in many different areas since XML data feeds are ever becoming the standard way to communicate related data between applications and systems.

In this script, I used many topics we’ve previously discussed and added a powerful object, Microsoft.XMLDOM. Essentially, DOM stands for Document Object Model– which is a way for the document to describe and relate the data it contains. Here is an example XML document header for “mydata”

<?xml version=”1.0″?>
<!DOCTYPE Mydata SYSTEM “mydata.dtd”>

This essentially in the first line tells us the file is an XML document, Version 1.0 to be specific, and in the second line tells us the Document Type Definition file that we can have the parser verify the XML file against. DTD’s and XML Schemas are beyond the scope of what we’re discussing but can be very useful becasue they define the rules by which a XML document must conform to be considered valid– however they are not required to be in an XML file.

After these lines the XML file has nodes and child nodes in it. This is where the bulk of our work was done going through the nodes and pulling out child nodes and values. In this illustration we’ll use the following URL to my XML Game data at 360voice.com (note the data will change over time, but the datastructure should stay pretty much the same)

As of this moment, the file looks like:

<?xml version=”1.0″ encoding=”ISO-8859-1″ ?>

<api>
<info>
<version>1.2</version>
<gamertag>jlees</gamertag>
</info>
<gamerscore>
<score>
<value>23740</value>
<date>3/20/2008 4:42:02 AM</date>
</score>
<score>
<value>23740</value>
<date>3/19/2008 4:45:18 AM</date>
</score>
</gamerscore>
</api>

Notice how the main Node (The “document” Node) is titled api? The XML Parser automatically read that entire node in at the load of the document. After that we have nodes called info and gamerscore that both contain data and/or child nodes.

the info tag contains the version and gamertag values, you’ll notice I used the gamertag value in the script to pull the name of the gamertag with this line of the script code after checking to see if the currently looped through tag had the name “info”:

WScript.Echo GetTagValue(x,”gamertag”)

See how that works? This example was pretty simple since it was just off the root. The score value and date were a bit harder to get at, but not to bad.

They are contained in a child node called “score”, but they are a child of gamerscore– so you’ll see that I check to see if the tag is “gamerscore” and then loop through the score tag separately looking for each instance of the node called score and pulling the tag value and placing it into an array called gamerscore.

All pretty straightforward. There are certainly better ways to deal with XML than writing code tightly around the XML itself, but this illustrates the use of Microsoft.XMLDOM and explains the heirarchial nature of XML nicely the way it’s been coded.

See if you can play around with the code and make it better! Thanks again to the folks at 360voice for providing the API and it’s documentation!

Happy coding and have fun!


Mar 20 2008   6:26PM GMT

Explanation: Working with Subroutines and Functions in VBScript



Posted by: Jerry Lees
Subroutines, Functions, Development, VBScript, DataManagement

I just realized in my haste to get out a piece of code celebrating the XBOX 360 contest, I negected to give a proper answer for our discussion on subroutines and functions in a vbscript.

In this installment, we’ll explain how to build a function and a subroutine a bit better. First, remember functions and subroutines are basically smaller pieces of your script — they essentially are the work horse of your script.

They both get passed information when they are called and preform their work according to what the information they have been given. These values passed can literally be anything you need to make the subroutine or function work but are generally only what the function needs to preform it’s work. You can reference the whole blog entry here.

Basically, you can build a subroutine like so:

Sub MySub(myvariable)

‘… your code here

End Sub

You would call this subroutine like so:

MySub XVariable
-Or-
MySub 10
-Or-
MySub “This Value”

Notice that I didn’t use Parenthesis, you don’t when calling a subroutine. The value you pass the subroutine can be variable (XVariable), a literal number (10), a string (”This Value”), or any other specific item you need to pass into the subroutine– even an array, providing you’re expecting the variable type!

Functions are the exact same as subroutines except in the label when you create them and in that they can return a value.

To create a function you:

Function MyFunction

‘… your code here

MyFunction = X

End Function

To call a function you use parenthesis, unlike a subroutine, like so:

X = MyFunction (XVariable)
-Or-
X = MyFunction (10)
-Or-
X = MyFunction (”This Value”)

Notice the line in red? This is the line of the function that does the magic of returning a value! It essentially works on the premise that the function name is a variable in the function that is always there. at the end of the function’s work the value is passed back to the calling routine as the return value– and it does this automatically.

Also notice how I changed the line to call a function? I placed a variable, X, in front of the function and set X equal the return of the function. You can also use a function in comparisons like so:

If Myfunction(10) = 1 then
‘your code here
end if

So, we’ve covered the creation and calling of a subroutine, the creation and calling of a function, how to assign a value to the return of a function, and how to use the return from the function.

From this point, you can use your imagination for when and where to use functions and subroutines!


Mar 14 2008   5:57PM GMT

Using XML in vbscript via Microsoft.XMLDOM to work with data feeds



Posted by: Jerry Lees
360voice, Microsoft.XMLDOM, XML, VBScript, DataManagement

In this installment I wanted to both celebrate and congratulate the winners of the ITKE Challenge that has been running over the last few months for an XBOX 360 ELITE system, among other prizes. I also wanted to write about XML use in vbscript as well so the challenge was how to accomplish both tasks…

Then I remembered a great community site, that I’ve been a member of for a little over a year or so, called 360voice. Basically, those guys have a truly awesome idea over there… I play games with my Xbox 360 and it blogs about the times we have—and I don’t have to do any work on my own. ;-) If you have a 360 and don’t have an account setup, go over and check it out, tell ‘em Jlees sent you. Heck, while you are at it watch my blog there and drop me a note.

At any rate, one of my challenges was to get everyone the same XML file, while not creating it myself because I wanted the script to be useful under certain circumstances. 360voice came through with their API Documentation! Think about it… now your scripting life has insite into your gaming life (and other’s as well) you could write a script to compare your achievements to your buddies, show the games you haven’t completed, and all sorts of other stuff. Why?? Because you can!

Consider this working code (that indecently pulls the XML directly from the website without saving it locally) that shows the last 10 days of gamerscore history for two gamertags in the output, in my case I chose mine, Jlees, and one of the owners of the site, changeagent, to do the comparison.. From this script alone you could graph your gamerscore and a buddies so you can compare and have irrefutable bragging rights about your gaming powers! (notice: that I put just about everything together we’ve talked about up to now in this one script, if your just joining us you might want to go back and brush up the last few weeks worth of blogs really quick. Also, I’ve noticed some cases where the sourcecode does not copy correctly, so I have uploaded the source to this article to my website here for you to download.)

Option Explicit

Dim GamerTag1,GamerTag2, GamerScore, Days, xmlDoc, x, y, Value, Count

GamerTag1 = “JLees” ‘change this to your gamertag
GamerTag2 = “ChangeAgent” ‘change this to your buddies gamer tag
‘ a quick note on the following line. It’s great the folks at
www.360voice.com gave us this API
‘ While you likely can change this to something other than 10 below, I strongly encourage you To
‘ limit it to less than a month. The pulling of this data will no doubt have an impact on their servers
‘ and excessive pulls will likely get you blocked, the API removed, or restricted.
‘ Basically, be a good neighbor.
Days = 10 ‘ change this to the number of days to pull.

DisplayTagHistory(GamerTag1)
DisplayTagHistory(GamerTag2)

Sub DisplayTagHistory(GamerTag)
 set xmlDoc=CreateObject(”Microsoft.XMLDOM”)

 ReDim GamerScore(Days)

 xmlDoc.async=”false”
 xmlDoc.load(”
http://www.360voice.com/api/score-getlist.asp?tag=” & GamerTag & “&num=” & days)
 for Each x in xmlDoc.documentElement.childNodes
   If x.nodename = “info” Then ‘ this is where the gamer tag is located in the node named “gamertag”
    WScript.Echo GetTagValue(x,”gamertag”)
   End If
 
   If x.NodeName = “gamerscore” Then
  Count = 0
  For Each y In x.childnodes  ’ this is where the score for that day is located
         ’ in a node named “value”
   GamerScore(Count) = GetTagValue(y,”value”)
   ’below we output the data. You could easily change the “vbTab & “:” & vbTab” to
   ’a , and create a CSV or write to a file. the world’s wide open from here.
   WScript.Echo Date-Count & vbTab & “:” & vbTab & Gamertag & vbTab & “: ” & GamerScore(Count)
   Count = Count + 1
  Next
   End If
 Next
End sub

‘note this function assumes only one node named the same as SrchStr is in the XMLTAG child node.
‘ if there is more than one, only the last value will be returned.
Function GetTagValue(XMLTag, SrchStr)
 for each Value In XMLTag.childNodes
    if ucase(Value.nodename) = Ucase(SrchStr) Then
     GetTagValue = Value.text ‘get the value in the node requested.
    End If
 Next 
End Function

The output, with the script untouched, should look like so:

 JLees
3/14/2008 : JLees : 23740
3/13/2008 : JLees : 23730
3/12/2008 : JLees : 23730
3/11/2008 : JLees : 23730
3/10/2008 : JLees : 23730
3/9/2008 : JLees : 23730
3/8/2008 : JLees : 23700
3/7/2008 : JLees : 23700
3/6/2008 : JLees : 23700
3/5/2008 : JLees : 23700
ChangeAgent
3/14/2008 : ChangeAgent : 12817
3/13/2008 : ChangeAgent : 12817
3/12/2008 : ChangeAgent : 12817
3/11/2008 : ChangeAgent : 12817
3/10/2008 : ChangeAgent : 12817
3/9/2008 : ChangeAgent : 12817
3/8/2008 : ChangeAgent : 12817
3/7/2008 : ChangeAgent : 12817
3/6/2008 : ChangeAgent : 12817
3/5/2008 : ChangeAgent : 12777

I only used ONE new thing in this code Microsoft.XMLDOM, which we’ll discuss in a later entry but I wanted to call your attention to the following line in this entry:

xmlDoc.load(”http://www.360voice.com/api/score-getlist.asp?tag=” & GamerTag & “&num=” & days) 

This line is the one where you would specify the path for the XML file, whether it is a local file or a file on the internet—like this rss feed to my blog. Also note that the DisplayTagHistory subroutine is highly focused to this XML feed and will likely need some work to get it to display another.

Enjoy!

Extra Credit: Can you modify the code to include the other owner of the 360voice site and compare his score with mine and changeagent’s? His Gamertag is Fatty Chubs.


Mar 12 2008   5:38PM GMT

Use of option explicit and the DIM statement in VBSCRIPT.



Posted by: Jerry Lees
Development, VBScript, Error control, Variable Types, VBScript Statements

As an answer to the extra credit portion of my posting a few days ago:

DIM in a script declares a variable to be used. It just simply creates the variable, nothing more. By default, vbscript will create variables on the fly for you as you use them the first time you use them.

There are other ways to create a variable as well, but create specific types of variables. Here are a few I can think of off the top of my head.

Const  - creates a Constant Variable, while it may seem line an oxymoron, they are sometimes very useful rather than risking typing a long value over and over again. Consider these examples Please note, they are abbreviated here for display purposes— please do not use them in code to launch a rocket to Mars ;-) .

Const Pi = 3.14159265358979323846264338327950288419716939937510582097494459230 ‘ Pi
Const GC = 0.62432998854355087099293638310083724417964262018052 ‘ The Golomb Constant
Const AC = 0.37395581361920228805472805434641641511162924860615  ‘ Artins Constant

By doing this we can type this in our code: 

Answer = Pi * GC * AC

Instead of:

Answer = 3.14159265358979323846264338327950288419716939937510582097494459230 * 0.62432998854355087099293638310083724417964262018052 * 0.37395581361920228805472805434641641511162924860615

And just imagine the mistakes we’d make if we had to type it a bunch of times!

Also there is This command:

Redim  - used to create a single or multi-dimensional array.

For example:

Redim StudentQuarterlyGrades(4) ‘ single dimensional array for grades for a student
Redim ClassQuarterlyGrades(4,13) ‘ a multidimensional array for quarterly grades for a class of 13

Enough of that tangent of extra information! The last  extra credit item was:

option explicit, which forces the writer of a script to declare their variables before they use them.

This can be very valuable and a huge time saver– though it requires a little extra work on the from side declaring variables before you use them. In fact, most programming languages, like c/c++, java, and others, require you to declare the variables prior to use as well as decalre what kind of value you will be putting in them.

Consider this code, without using OPTION EXPLICIT:

StudentFinalGrade = 100
StudentHomeworkGrade = 100

StudentCourseGrade = ((StudentFialnGrade + StudentHomeworkGrade)/200)*100

Do you see the problem? I spelled final wrong in the last line StudentFialnGrade.

Some poor student will get a F (50%), instead of an A (100%) because of that mistake. However, The same code with option explicit and proper DIM statements below (yes, you can declare multiple variables on one line with a comma):

Option Explicit
Dim StudentFinalGrade, StudentHomeworkGrade

StudentFinalGrade = 100
StudentHomeworkGrade = 100

StudentCourseGrade = ((StudentFialnGrade + StudentHomeworkGrade)/200)*100

Yields the following error, pointing to the line and the variable that is either misspelled or not decalred:

… Untitled4.vbs(7, 1) Microsoft VBScript runtime error: Variable is undefined: ‘StudentFialnGrade’
 

Notice how easy that is. Trust me on this. Get into the habit of starting every script with option explicit and using DIM to declare your variables… while it may not matter for 20 -40 line scripts, you will notice it in 100 or 1000 line scripts– and wish you had done it when you spend several hours tracing down why a calculation or string value is coming out differently than you expected!


Mar 10 2008   3:33PM GMT

Working with Subroutines and Functions in VBScript



Posted by: Jerry Lees
Development, VBScript, Functions, Subroutines

In this installment, we’ll discuss the advantages of using Subroutines and Functions in your script rather than using a all-in-one script that runs from start to finish. I’ll only give a breif over veiw of subroutines and function, but more information on them can be found in the VBScript User’s guide and Language reference.

First, Functions and subroutines are basically smaller pieces of your script. They are generally a part that completed a specific task in the script and are very helpful in accomplishing the following:

      Creating reusable code to use in other scripts without having to re-write the code
      Making your code more readable
      Using the same set of code multiple times in the same script without a loop of some type.
      Helpful in debugging a script and disabling a section of code
      Helpful in organising the logic of the script into smaller bite sized pieces

They essentially are the work horse of your script. In General, I try to keep all the logic of a script in a Function or a subroutine– that way If I have to make modifications I’m only going to at worst break a small (but possibly important) piece of the script. Remember, Subroutines and functions can call other subroutines and functions– so they are not limited to just being used within your main script– Infact, a single function or subroutine can call itself! This is outside the scope of this posting, but is called a recursive funtion or subroutine.

They both get passed information when they are called and  preform their work according to what the information they have been given. These values passed can literally be anything you need to make the subroutine or function work. These values are generally only what the function needs to preform it’s work. For example:

Say you need to calculate the price you pay for an item at the store, so you can have exact change in cash. Think about what information you need. You just need the price of the item and any sales tax on the item, you don’t need anything else like where the store is or who the cashier is. That’s essentially what a subroutine is!

Now, Functions and subroutines are VERY similar. In fact, there is only one major difference in the two of them. They both offer a way to better organize your code into bite sized chunks, create re-usable sections that are easier to manage and modify, and they both preform a very specific task.

The only difference is that a subroutine does it’s work and deals with it’s result inside itself without communicating the end result back to the routine that called it to run.  So it’s kind of a loner… just does it’s work and doesn’t bother anyone else with the details or the result. This is useful for file or screen I/O where you don’t need any information returned to you. Basically, it’s a script all in itself. In our earlier example the subroutine would need to print out or do something with the values calculated and no other area of the program would be aware of where the result.

A function on the other hand will communicate back to the calling routine some value… possibly the result of some calculation, like our total price of the item, or an error condition for the calling routine to process and deal with in a manner that is fitting for the situation.

In my example below I provide you with both examples of a subroutine and a function to add two numbers together. Notice that when I call the subroutine in vbscript I do not use parenthesis around the values I pass to the routine, but with a function I do use them. This is just simply the way it is done in VBScript and will result in an error if your do it the other way around.

Option Explicit
Dim ReturnValue

TestSub 2,2 ‘ subroutine call– notice no ( ) around the two values!?!?!
ReturnValue = TestFunction (2,2) ‘function call– notice the ( ) around the two values… plus some thing else!
WScript.Echo “Function returned: ” & ReturnValue

‘ end of main code

Function TestFunction (Value1, Value2)
‘ Function to add two numbers and RETURN the value to the calling routine.

Dim Sum
 Sum = value1 + Value2
 WScript.Echo (”Functions: All your work is done here and used here, but can be sent back to the main script.”)
 WScript.Echo Value1 & ” + ” & Value2 & ” = ” & Sum

TestFunction = Sum

End Function
Sub TestSub (Value1, Value2)
‘ Subroutine to add two values together… notice all the work is done and used here?

Dim Sum
 Sum = value1 + Value2
 WScript.Echo (”Subroutines: All your work is done here and used here.”)
 WScript.Echo Value1 & ” + ” & Value2 & ” = ” & Sum

end Sub

Play with this code… see if you can figure it out. In a few days I will explain it in a bit of better detail. Take note of how I build the function, subroutine, and see if you can figure out the line that does the magic of returning the value from the function. 

Extra Credit: Did you notice the line that had option explicit and the lines that have Dim in them? What do they do? Post a comment and I’ll let you know in a few days.
 


Mar 7 2008   10:22PM GMT

Eventlog search tool — Find quick help with windows event log entries



Posted by: Jerry Lees
DataCenter, Exchange, Networking, Security, Administration tools

While not VBScript related, I found this Microsoft Eventlog and Error Message Search a few days ago as I stumbled around looking for tools that I thought network administrators would need on my site that I’ve been toying with– I had to share the tool with you as well!

 The tool itself is an awesome resource, similar to EventID.net– except it’s FREE and it comes from Microsoft themselves providing links to Microosft content about the event entry or error message.

 You can search for any combination of the following:

Microsoft Product|
Version
Message ID
Event Source
File Name
Language

When you do it takes you to a search result page that lists the available results for your specific search, each seem to have not only an example of the message, but also an explanation of what the event means…. and the best part a section entitled User Action that gives a possible solution for the problem!

 Enjoy the tip!


Mar 4 2008   1:57AM GMT

Determining properties and methods used in a WMI object for use in a vbscript.



Posted by: Jerry Lees
VBScript, DataCenter, Development, WMI, Windows Management Interface

In this entry we’ll take a look at the microsoft documentation for win32_printerdriver and determine how we can determine what values to use to get data once we’ve created a script to get set of data back from a WMI object into a collection object. Most of the previous discussion can be read, in order in my blog but here are links in order, if your just tuning in:

Finding HP Printers using PCL6 Drivers with WMI
Using error control in a vbscript to recover from odd errors
Using Set, GetObject, ExecQuery, and For Next in VBSCRIPT to use WMI objects

Microsoft has a great deal of documentation here on the win32 WMI classes.  However, here is an excerpt from their win32_Printer class. Most of their documentation is written for c/c++ programmers it seems– don’t let that scare you off, you don’t need this code in yours nor do you need c/c++ experience to use them.

Below you see the first line creates a “class” called Win32_PrinterDriver that is of a type called CIM_Service. Essentially, a class contains data and tools you can use in your programs. CIM_Service is just the name of the data type the class is created as– you’ll see references to CIM all over the place with WMI. It stands for Common Information Model, check out the preceding link for more information.

After that, the items in curly braces ( {} ) are the actual names of the properties and what types of data they contain. Again, as long as you are using the data in strictly Vbscript code you don’t even need to know what the type is– VBSCRIPT takes care of that for you. However, on ocassion you’ll see a “type mismacth” error in your code. This is simply referring to the fact that you have put a value in a variable of one type (a string for example) into a variable that is meant to have another type (an integer for example), typically this happens when you use a external component that was written in another language that is more strict about the data types than vbscript, like c, c++, or others. (Which is almost all of them outside of the Visual BASIC family)

class Win32_PrinterDriver : CIM_Service
{
  string Caption;
  string ConfigFile;
  string CreationClassName;
  string DataFile;
  string DefaultDataType;
  string DependentFiles[];
  string Description;
  string DriverPath;

};

In the code I wrote for this series I used Wscript.echo to print the data to the screen inside the For Each/Next loop, like so:

Wscript.Echo “DriverPath: ” & objItem.DriverPath

Remember, objitem was a collection of printer driver information objects?
Notice the last part of that line, .DriverPath?
Notice the last line I gave you from the microsoft documentation?

Yeap, they are both DriverPath! There’s a reason… they are the same thing! Essentially, ANY of the items listed in the Win32 classes can de used in conjuction with a collection object– providing you have collected the same type of object with a WMI object before hand! So this documentation is like GOLD for a systems administrator! So, if you didn’t take a hour or 50 before when I gave you the link check it out here again.

For example, I didn’t use the property Version in my original code. If you needed this information in the program you could add another line in the For Each/Next loop to gather that information as well! Like so:

WScript.Echo “Version: ” & objItem.Version

You can do that with any of the properties and methods in the win32_printerdriver class, and it expands beyond that to all of WMI.

One thing to keep in mind with much of WMI is that it is dependent on the driver or hardware manufacturer to provide the information– not all manufacturers provide that information 100% reliably, so you’ll have to play and tweak what your hardware vendor does give you. My bet is even if it’s not 100% of all the information available, it will be more than you had to start with without hours of digging.

So, here is the original code again. Take a few minutes to play around with the code and the win32_printer driver documentation and see what interesting pieces of information you can pull out of WMI.


On Error Resume Next
strComputer = “.”
Set objWMIService = GetObject(”winmgmts:\\” & strComputer & “\root\cimv2″)
Set colItems = objWMIService.ExecQuery(”Select * from Win32_PrinterDriver”,,48)
For Each objItem in colItems
Wscript.Echo “ConfigFile: ” & objItem.ConfigFile
Wscript.Echo “DataFile: ” & objItem.DataFile
Wscript.Echo “DriverPath: ” & objItem.DriverPath
Wscript.Echo “Name: ” & objItem.Name
Wscript.Echo “OEMUrl: ” & objItem.OEMUrl
WScript.Echo “_________________” & vbcrlf
Next

That concludes this series!

 Extra Credit: Can you modify the code above to pull actual printer hardware/software data from Win32_Printer? Hint: stay clear of the properties with a [] after them for now, they will potentially trip you up. And also, remember just because it pulled back one value that was blank doesn’t mean you did something wrong– some items aren’t populated by hardware vendors to WMI unfortunately.


Mar 3 2008   9:11PM GMT

Using Set, GetObject, ExecQuery, and For Next in VBSCRIPT to use WMI objects



Posted by: Jerry Lees
SQL, Development, VBScript, Networking, Objects, VBScript Statements

In my last blog entry I explained error control via on error resume next and on error goto 0, there are other ways as well– but for now this should work to get us by.

Next well discuss the Set, GetObject, ExecQuery, and “For Each” commands in the script we worked with, these are on lines 3, 4 and 5 below.

The script was basically (line numbers included as a reference):

1. On Error Resume Next
2. 
strComputer = “.”
3. Set objWMIService = GetObject(”winmgmts:\\” & strComputer & “\root\cimv2″)
4.
Set colItems = objWMIService.ExecQuery(”Select * from Win32_PrinterDriver”,,48)
5.
For Each objItem in colItems
6. 
    Wscript.Echo “ConfigFile: ” & objItem.ConfigFile
7. 
    Wscript.Echo “DataFile: ” & objItem.DataFile
8. 
    Wscript.Echo “DriverPath: ” & objItem.DriverPath
9.
     Wscript.Echo “Name: ” & objItem.Name
10.
   Wscript.Echo “OEMUrl: ” & objItem.OEMUrl
11.
   WScript.Echo “_________________” & vbcrlf
12.
Next

The Set command basically tells cscript (or wscript) to assign the value of a variable to be the value of another or creates an object. For all intensive purposed, you can think of an object as a piece of specialized code that is already written that you can call from within your program and use as if it were your own. An object can contain many different types of values, that are referenced by names. These names are either properties (values) or methods (functions to do something and probably give you a value back).

Next, the GetObject command. this is the true heart of our WMI script. In fact, this is where almost all the magic happens! The Getobject comamnd lets us use pieces of code outside of our application as if we had written them on our own– the plus being that we don’t have to write them. In this case it is a WMI call to retrieve an object called “winmgmts:\\.\root\cimv2″.

This object is the root WMI provider that is built into the OS and the period represents the local machine, to get other machine you would specify it’s name instead– this is why we used a variable in the script. (Remember, scripts are powerful when they are reusable for the same situation at a different time, so try to use variables where ever you think a piece of information could change in the furture to allow you to reuse the script.) This WMI provider returns a WMI object that allows us to reference and use the piece of the OS that deals with WMI. Notice we SET the object to the variable objWMIService in the line?

 In the next line of code we actually USE it, again another SET command. But this time we use:
… objWMIService.ExecQuery(”Select * from Win32_PrinterDriver”….

The execQuery method is a part of the WMI classes Microsoft has written, and we are simply calling it to preform work. In this case, we are constructing a call to pull back all the printer drivers. The part in the quotes works exactly like a simple SQL statement would operate. Essentially in english it works like– Select all values from Table containing the printer driver information. This “table” contains lots of information on the printer drivers, I’ve only chosen to show a few items from the table, you can get more information here.

After this command completes, colItems will contain a collection of objects that each have properties named the same as the columns in the table. We use the For Each command on line 5 to loop through each member of a collection one at a time and do something with the data (or to the data). The Next command on line 12 loops back to the beginning as long as there is another object after the one currently being used in the collection.

That’s it! It’s pretty easy stuff, once you get the concepts down. Remember, The WMI object is used to execute a query against the WMI database on the system. This query returns a collection of objects containing data for the query you built.

The actual data returned (and names of methods and properties used to get the data) depends on the query you specified. More on that next time!