The VBScript Network and Systems Administrator's Cafe:

April, 2008

Apr 30 2008   2:20PM GMT

Using VBScript to create Word documents automatically with the Word.Application Object



Posted by: Jerry Lees
Word.application, VBA, DataManagement, VBScript, Developer documentation, Documentation

I recently had a project that required me to create a ton of documentation from data that was already stored in files elsewhere on the network– just not in the format that was required and readable by every day people within IT. (Basically, non-administrators) This project would have required a TON of copy and paste operations or a whole lot MORE reworking of a document, plus I was on a tight deadline. So I decided to use a little VBA (Visual Basic for Applications) knowledge I had picked up in the past to work with the Microsoft Word Application interface and do the job, with only minor reworking after the fact to really tidy up the document.

First, let me clarify. Most of my scripts I use here require nothing more than the items I mentioned in my first posting (Getting Started Writing VBScript to Administer a Windows 2000 or 2003 Network) on this blog… a VBScript editor. (Notepad will do… but you’ll likely quickly want something a bit more powerful before long.) The scripts I discuss in this series are one exception, for these scripts we discuss in the next few articles we will need to make sure you have Microsoft Word installed where ever you run the script. However, for the purposes of this type of work your workstation should work fine and will likely already have Microsoft word installed! Bonus!

The “magic” component we need to call and create an object from is called Word.Application, as you’ll see below, it’s pretty easy to create a word document from VBScript and then have auto generating documentation!

The next sections of code will show you how to do various tasks with in word. Many sections are not scripts on themselves, but in fact snippets that could be placed into the first script prior to the remark for testing. The first snippet, creates a word document and saves it to the root of your C: drive. When you run this it will run, but create a blank word document– much like if you right clicked somewhere and selected New/Microsoft Word Document. Here are some common tasks in word I use:

Create a new (empty) Word Document and save it to c:\testdoc.doc
Set objWord = CreateObject(”Word.Application”)
‘note: if you don’t want word popping up and displaying as this is built– set this next line to False

objWord.Visible = True
Set objDoc = objWord.Documents.Add()
’save the Word Document
objDoc.SaveAs(”C:\testdoc.doc”)

Setting the Font type
objSelection.Font.Name = “Arial”

Setting the Font Size
objSelection.Font.Size = “18″

Adding Text
objSelection.TypeText “Add your text here”
objSelection.TypeParagraph()

Setting the typeface to bold
objSelection.Font.Bold = True

Closing the word document (generally done after saving)
objWord.Quit

These should get you started playing with VBScript to create word documents. For more information on working with Microsoft word in VBScript look here at Microsoft’s site, while it’s not related exactly to VBScript– it should give you enough information about the interface to get started.

 Next time, I’ll share a script to document settings in Group policy with a word document through a combination of using Word.Application and Microsoft.XMLDOM.

As always, , 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!

Apr 25 2008   3:19PM GMT

How VBScript variable types are represented as binary numbers



Posted by: Jerry Lees
Variable Types, VBScript

In a previous posting,  Converting variable types in VBScript from one type to another type, I discussed very briefly binary numbers and promised to write another entry with more detail. If you recall we we were discussing the size a number takes up to represent it in binary form.

Everyone is comfortable with the numbers 1 and 0, even in binary. And if you’re in IT, you’re probably even comfortable with binary 10, which isn’t Ten– it’s two. Normally we count in tens (with ten digits in each place), but computers count in twos (with only two digits in each place), which is base-2 instead of base-10 like we are used to counting.

 Consider this base-10 table with the column labels at the top and the number of each column below.

10000

1000

100

10

0

9

8

1

5

3

This might look a bit abstract the way it’s presented. But if you think back to elementary school the columns in a number represent the 10’s, 100’s, etc for the number. But the number is 98,153 or (90,000 +8000+ 100+50+3)

Now consider the following binary number, again with the column label at the top and the number of each column at the bottom:

16

8

4

2

1

1

0

1

1

1

This looks a bit more cryptic, but it’s actually simpler– we’ve just been trained to think in decimal. To do the first one we actually had to do multiplication in our head. It wasn’t (90,000 +8000+ 100+50+3)— it was actually(9* 10,000) + (8* 1000) + (1 * 100) + (5 * 10) + (3* 1)… That’s rather confusing when you spread it out, isn’t it? but with only 1’s and 0’s we don’t need to do multiplication. (Because 1 * anything is the number, and 0 times anything is 0)

So this is simply 16+4+2+1, or 23! It’s just a matter of getting to start thinking in powers of 2!

Now, Since I’ve shared with you previously that a double is larger than an integer, with respect to space, we’ll continue with that example. If you refer here you’ll notice that an integer is 2 bytes in Size where a double is 8 bytes in size. What’s 400% more space among friends, right? Quickly doubles can get out of control is you’re using bunches of them, or placing them in a Database one item at a time… This is sometimes where developers eat up all our space on the servers, in addition to the backup of the backups in the backups folder that’s stored in a Do not delete - Save this stuff folder. ;-)

The other thing that can be VERY bad! is using a variable type that is to small. Did you notice in the previous link that in Integer represents -32,768 to 32,768? What happens if you add 1 to 32,768? The answer for us is, of course, 32,769! The problem is computers can’t represent that number in an integer so you get a overflow and the number represented actually looks like -32768 to the computer!

 The moral of the story is to always try to use the right type of variable if a variant doesn’t work for you, and if you plan on using anything other than VBScript, VB, VB.NET, or VBA to create an admin tool– get accustomed to the different variable types.

Enjoy!

Extra credit: 10 in base-10 numbering is Ten, 10 in base-2 numbering is 2… what is 10 in Base-16 numbering and what is it commonly called?


Apr 25 2008   1:26AM GMT

Reporting CPU usage by saving it to a file with the VBScript filesystem object



Posted by: Jerry Lees
Error control, File System Object, Functions, VBScript, Scripting.FileSystemObject

Last time, in my entry entitled VBScript to check CPU and Processor performance counter statistics using WMI, I asked you to modify the code I gave to include the access method type in the function. If you haven’t read the article, take a second to go back and look it over and digest the code because this article is identical to that one, except some added features.

Again I got a rather quick response to the extra credit item that I placed at the end if the article. Basically, you just need to change the code in three places to accomplish this task. We could then use this code in our previous example to create a CSV file for trending and graphing of CPU usage on a server! Here is an example of the code to do this task.

I encourage you to play around with the various methods of file access both with an existing file and a new file that doesn’t exist.

Below is a working example of the code:

Option Explicit
On Error Goto 0
Dim strSrv, strQuery,Errors
Dim Counter, Timeframe, Delay

Delay = 1000 ‘1000 Milliseconds to a second
Timeframe = 300 ’seconds (5 minutes)


strSrv = “.”
For Counter = 1 To Timeframe
 Errors = WriteTextFile (”c:\cpu-usagelog.csv”, GetFormattedCPU (strSrv), ForAppending)
 WScript.Sleep Delay
NextConst ForReading = 1, ForWriting = 2, ForAppending = 8Function GetFormattedCPU(strSrv)
    Dim objWMIService, Item, Proc, start
   
    start = Now()
  
    strQuery = “select * from Win32_PerfFormattedData_PerfOS_Processor”
    Set objWMIService = GetObject(”winmgmts:\\” & StrSrv & “\root\cimv2″)
    Set Item = objWMIService.ExecQuery(strQuery,,48)
    WScript.Echo strQuery
    For Each Proc In Item
       GetFormattedCPU = GetFormattedCPU & Proc.PercentProcessorTime & “, “
       wscript.echo “Processor ” & Proc.Name & ” = ” & Proc.PercentProcessorTime
    Next
   
    GetFormattedCPU = GetFormattedCPU & start  
 
End Function
Function WriteTextFile (OutputFile, Data, AccessType)
    Dim wrtlog, fso
 
    On Error Resume Next
    Set fso = CreateObject(”Scripting.FileSystemObject”)
    Set wrtlog = fso.OpenTextFile (OutputFile, AccessType, true)
 If Err.Number <> 0 Then
  Set wrtlog = fso.OpenTextFile (OutputFile, ForWriting, true)
 End If
    wrtlog.WriteLine(Data)
    WriteTextFile = Err.Number ‘You can use Err.Description here to debug.
    On Error Goto 0
End Function

You now have all the pieces for a fully functional performance logging script, so you’re well on your way to being able to troubleshoot problems deep in the night without getting up and turning on Perfmon. The creates a comma separated value file called cpu-usagelog.csv at the root of the C: drive while the output looks similar to the last time, except it is repeated and I put a time/date stamp in the code by using a new command, now().Also, pay attention to the error handling around the line that writes the data to the file, you’ll likely not see an error related to the file not existing and you using the append access methods, because I’ve checked for it while opening a file. Lastly, notice the for next loop around the function call to call it Timeframe times (Timeframe is multiplied time the sleep Delay to get how long it will capture data). Also notice another new command: Wscript.Sleep, which basically pauses the execution for the number of milliseconds you specify in Delay.

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: Try and modify this script to monitor something else that is useful to you. Let us all know how you’ve used it.


Apr 17 2008   8:52PM GMT

Creating text files using the Scripting.FileSystemObject with VBScript



Posted by: Jerry Lees
FSO, File System Object, Scripting.FileSystemObject, VBScript, log files, Functions

Well, I didn’t expect the cat to get out of the bag quite so quickly! (Congratulations go out to Stoinov for getting the correct answer I was thinking of so very quickly!) So while he’s been sleeping during his night, which seems to be my day… I thought I’d throw together a quick “Write a text file” script together for you all. (A little trivia for you all in the United States, that I found hard to believe when I learned it… VBScript, and VB for that matter, is in English regardless of where you are in the world. If you’re on a Japanese system writing VBScript, your using the same language as us folks in the United States. Talk about portable code!)

Back to the matter at hand, this script doesn’t do anything terribly spectacular– by itself. All it does is opens (or creates) a text file named what you call it where you specify. The heart of the script is the WriteTextFile () function, which accepts two pieces of data; a full path to a file name and the data you want to write. That’s it! But—- this function will let you write logs, CSV (Comma Separated Value) files or any other form of text file from any type of script for which you choose to use it!

A quick little note on the access method I hard coded into the script. You  will notice three constants used ForReading, ForWriting, and ForAppending these are there so you could change the mode easily without having to go to the documentation for the OpenTextFile Method of the Scripting.FileSystemObject and figure out what numbers to use to change the access method. you simply just need to change the access method from ForReading on the OpenTextFile line of the script to accomplish this task. An excerpt of the Microsoft documentation for the values and descriptions are listed below, for your reference.

Constant Value Description
ForReading 1 Open a file for reading only. You can’t write to this file.
ForWriting 2 Open a file for writing.
ForAppending 8 Open a file and write to the end of the file.

Notice it has a ForAppending attribute? If you wanted to … say log a series of collected values over a number of calls to the script you would have to change the access method to appending, however, keep in mind that ForAppending assumes the file already exists and you will receive an error if it doesn’t.

So, here is the script to write a file…

Option Explicit
Dim Error

Error = WriteTextFile (”c:\test.txt”, “I created a text file with VBScript!”)
If Error = 0 Then
    WScript.Echo “File Written Correctly.”
Else
    WScript.Echo”Error number ” & Error & ” occurred.”
End If

Function WriteTextFile (OutputFile, Data)
    Dim wrtlog, fso
 
    ’these are constants for the OpenTextFile method’s file access modes
    Const ForReading = 1, ForWriting = 2, ForAppending = 8
  
    On Error Resume Next
    Set fso = CreateObject(”Scripting.FileSystemObject”)
    Set wrtlog = fso.OpenTextFile (OutputFile, ForWriting , true)

    wrtlog.WriteLine(Data)
    WriteTextFile = Err.Number ‘You can use Err.Description here to debug.
End Function

That’s it. Small, but a VERY powerful tool to add to your tool belt in scripting.

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 modify this function to accept a third parameter for the access method? I invite you to leave a comment and I’ll let you know if your on the same track as I am. Comments are always welcome!


Apr 16 2008   7:11PM GMT

VBScript to check CPU and Processor performance counter statistics using WMI



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

By now, if your reading my blog you’ve had a chance to play with the script I posted for Using VBScript to gather server performance counter data with WMI . But I think I might know what you’re thinking– “Hey, that’s cool… but I could careless about knowing how much non-paged pool memory there is being used on the system! I need to track something useful, like processor utilization or  something else!

Well, you can– and here you go!  As always the code itself is available on my website in the File Depot if you’d like to avoid copy/paste problems or you don’t want to type the code yourself.

This script has two functions in it, GetFormattedCPU() and GetRAWCPU() which both do the same thing, except that one uses a raw performance counter (Win32_PerfRawData_PerfOS_Processor) and the other uses a preformatted counter (Win32_PerfFormattedData_PerfOS_Processor) to get the information from the system. These two counter types, as you will see, give you very different numbers and for the most part you should probably stick with the preformatted counters if at all possible so you don’t have to do a ton of math to get meaningful data.

The functions both return a Comma Delimited string that contains the CPU percentage usage for all processors in the system. Note that, on my dual core system I get 3 numbers– respective to the return value; Processor 0, Processor 1, and _Total. This should work equally well on Physical SMP systems that are either single or Dual Core, but I suspect on a single core system with more than two processors you will get two numbers that are identical… unfortunately, I no longer have a single core system I can test on.

As always, the code is written in such a way that you can replace the “.” with a “server name” and it will work remotely on a system– providing you have administrative rights. Here is the code:

Option Explicit
On Error Goto 0
Dim strSrv, strQuery

strSrv = “.”

WScript.Echo GetFormattedCPU(StrSrv)
WScript.Echo”______”
WScript.Echo GetRAWCPU(StrSrv)

Function GetFormattedCPU(strSrv)
    Dim objWMIService, Item, Proc
   
    strQuery = “select * from Win32_PerfFormattedData_PerfOS_Processor”
    Set objWMIService = GetObject(”winmgmts:\\” & StrSrv & “\root\cimv2″)
   
Set Item = objWMIService.ExecQuery(strQuery,,48)
    WScript.Echo strQuery
    For Each Proc In Item
       GetFormattedCPU = GetFormattedCPU & Proc.PercentProcessorTime & “, “
       wscript.echo “Processor ” & Proc.Name & ” = ” & Proc.PercentProcessorTime
    Next
 
End Function

Function GetRAWCPU(StrSrv)
      Dim objWMIService, Item, Proc
    
      strQuery = “select * from Win32_PerfRawData_PerfOS_Processor”
   
      Set objWMIService = GetObject(”winmgmts:\\” & StrSrv & “\root\cimv2″)
      Set Item = objWMIService.ExecQuery(strQuery,,48)
     WScript.Echo strQuery
     For Each Proc In Item
         GetRAWCPU= GetRAWCPU & Proc.PercentProcessorTime & “,”
         wscript.echo “Processor ” & Proc.Name & ” = ” & Proc.PercentProcessorTime
    Next
 
End Function

That’s it!! As a point of reference, the output of this script looks as follows: 

select * from Win32_PerfFormattedData_PerfOS_Processor
Processor 0 = 0
Processor 1 = 0
Processor _Total = 0
0, 0, 0,
______
select * from Win32_PerfRawData_PerfOS_Processor
Processor 0 = 273670781250
Processor 1 = 275960625000
Processor _Total = 274815703125
273670781250,275960625000,274815703125,

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 guess why I would have messed up your output from the functions in this script by separating the numbers with commas? I invite you to leave a comment and I’ll let you know if your on the same track as I am. Comments are always welcome!


Apr 13 2008   1:40AM GMT

Converting variable types in vbscript from one type to another type



Posted by: Jerry Lees
Development, VBScript, Variable Types, VBScript Statements, Functions

In a previous posting, titled Variable types in VBscript and their upper and lower limits– just prior to my Rant about CAPTCHA, we discussed the types of variables and why you might want to use them and I showed you a few scenarios where you could get unpredicatable results by not using the proper variable type. If you haven’t had a chance to read it yet, you might want to go back here before continuing.

In this installment We’ll discuss the challenge created by using these variable types specifically. Remember, I said that if you use pieces of code or a COM object written in another language it may require a certain type of variable when you call it from your script. (Note, VBScript generally does a good job of converting for you behind the scenes, but it is a best practice to do the conversion on your own first.)  You might be thinking, “Why not just use a double for everything, that covers a wide enough amount of numbers that I’ll never be able to use a number that high?”

Well, the reason is the size of the amount of data it takes because a larger number takes more bits in binary to be represented– therefor the larger the number (or more correctly the RANGE of the variable type) the more space it will take to store it. (A binary lesson may be in order, but not today.)  The last reason is related to the size as well, it takes more processing power to deal with larger numbers because the bus of the CPU is only so wide, and it must sometimes bring the number across the bus in two steps, thus taking more time. Therefore, if you use numbers to big your  scripts can run slower. When I mean slower, I’m only talking about fractions of a second for the work to be complete, but slow scripts tend to each your life away a millisecond at a time… Imagine something being a millisecond slower but you have to do it 100,000 times. Now you’re looking at almost 2 minutes eaten away.

Now, We discussed the types of variables last time, below you will find a table that shows you the function that converts one variable type to another and a link to a useful site showing you how to use the function. Yes, a function. These get fed a number of one type and return a number of another, so you’ll need to assign the return to another variable when you call them.  (Note: the site referenced uses document.write in it’s examples, to use the examples in VBScript simply replace document.write with a wscript.echo)

VBScript Type Conversion Functions

Function Description
CBool Converts any nonzero value to True and 0 (zero) to False.
CByte Converts an expression to a Byte value.
CCur Converts an expression to a Currency value.
CDate Converts an expression to a Date value.
CDbl Converts an expression to a Double value.
CInt Converts an expression to an Integer value. If the fractional part of the expression is .5, CInt will round the value to the nearest even number. For example, 3.5 will be rounded to 4, and 6.5 will be rounded to 6.
CLng Converts an expression to a Long value.
CSng Converts an expression to a Single value.
CStr Converts an expression to a String value.

This information should be very helpful to you in coverting variables from one type to another in the future. The thing to remember is that you don’t always need to do this, but if you’re getting wierd results in your script; check for uninitialized variants, variables of one type (or variant) that are being used with a external piece of code from another language, or for places where a return value is one type and you use it as another.

Enjoy!

Extra credit: What happens if you have a variable (of any type) and add enough to it to cause it to go above the maximum value of the variable type? What’s this generally called?


Apr 7 2008   5:19PM GMT

Rant: Anyone else dislike those “enter the letters you see below” confirmation pages?



Posted by: Jerry Lees
Security, CAPTCHA

Ok, you guys know I try to at least stay on topic with respect to systems administration… but this time, as a systems administrator, I have to just share my complete frustration with a technology in use these days entirely to much, in my opinion.

That technology is the use of the automated images that are shown on pages that you have to enter the text shown in the image. I can never get them right the first time, but this one takes the cake!
Huh?

 This has simply got to be the WORST one I have ever seen! I mean, I see gsp there– but what are those other letters? tun? tia? tian?tim? lun? I gave up.

Most sites do this so that scripters will not be able to write scripts that automatically post comments to discussion boards, like spam e-mails, with no real person actually doing the posting. It’s supposed to “verify your humanity”– however, you’ll have to take my word for it– I am human! If your reading this and you own a  site that does this to us or are considering it– please find a better way to protect us from the spam bots!

 Some other ways they do this is with multi colored text. And while I’m not color blind, they generally do it with reds, greens, and blues– three colors that are hard to see if you are color blind.

All this trouble simply because some yahoo thinks he’s going to get rich by posting comments and sending e-mails about prescription drugs, a stock tip, or some other stuff. (We’ve all seen them, so I don’t have to go into detail here. Thankfully.)

At any rate, thank you for listening… back to your regularly scheduled systems administration duties. If get a chance post a comment with your favorite experiences with this frustration, I’m sure we’d all love to read them!


Apr 6 2008   12:17AM GMT

Variable types in VBscript and their upper and lower limits



Posted by: Jerry Lees
Development, VBScript, Variable Types

I just realized that the direction I’m headed with this blog (atleast a few posts from now) requires that I give you some more background information beyond what I’ve already done.

 Previously, I’ve talked about variables and given you a few types in passing– but never detailed the different types that are available to you as a script writer.

To that I say, “VBscripts default variable type is a Variant, which can hold any type of value you need to put in it without any work at all on your part.”

“WAIT?!?!!”, you say, “Here you are harping on us to be lazy and now you’re about to go through a big posting on variable types when the one you just mentioned should work fine for me!??”

Yes, a variant will work just fine for you for the most part. But it does do some funny things with variables because under the hood it does the conversion for you. Some even say using variants slows things down. Sometimes in VBscript you need to interface with an external COM dll or some other program and the other variable types will be needed because the call to the DLL will break if your variables aren’t properly cast into a type. Also, variants do funny things to numbers… take this simple example.

x = 2.0000
WScript.Echo x

 When you run this it simply prints:

2

No, No, No! I set x to 2.000 not 2. You might be thinking that 2.000 = 2 from your math days and you’d be right except some of your science folks out there will agree that sometimes you need to communicate precision as well. In science, 2.000 communicates that you’ve MEASURED something to the thousandth place to be exactly 2.000. Frankly, that can sometimes take work and if you’re lazy and you do all that work you want credit for it, right? (See how I brought that ramble back full circle? Be lazy!)

Also, It does some funky things with variables you’ve never set to a value as well. Since Variants are just that– you can use them for strings, like for a URL “http://www.360voice.com/” and numbers like 100. No problem, right? Again… Possibly it’s a problem… Consider this scenario in your script (with nothing else in the script): 

WScript.Echo y
WScript.Echo y + 1

This prints the following (between the _ characters below on two different lines to show you what happens):

_

1
_

See it? The first echo of y appears blank– yet when I add it to the number 1, I get 1!  That’s because if you don’t put a value in a variant variable it treats it is 0 if it is used in the context of a number and as an empty string (or NULL (Not “”, or the empty string) for you C/C++ programmers out there) if you use it in the context of a string. Big difference huh? Same Y, but two different values– empty and 0! (On a side note, think about empty with respect to a file’s contents– Empty takes no space at all and 0 (zero) takes a whole byte in a file.)

Now that you see some slight differences, consider the following types of variables in the table below: 

Subtype Description
Empty Variant is uninitialized. Value is 0 for numeric variables or a zero-length string (”") for string variables.
Null Variant intentionally contains no valid data.
Boolean Contains either True or False.
Byte Contains integer in the range 0 to 255.
Integer Contains integer in the range -32,768 to 32,767.
Currency -922,337,203,685,477.5808 to 922,337,203,685,477.5807.
Long Contains integer in the range -2,147,483,648 to 2,147,483,647.
Single Contains a single-precision, floating-point number in the range -3.402823E38 to -1.401298E-45 for negative values; 1.401298E-45 to 3.402823E38 for positive values.
Double Contains a double-precision, floating-point number in the range -1.79769313486232E308 to -4.94065645841247E-324 for negative values; 4.94065645841247E-324 to 1.79769313486232E308 for positive values.
Date (Time) Contains a number that represents a date between January 1, 100 to December 31, 9999.
String Contains a variable-length string that can be up to approximately 2 billion characters in length.
Object Contains an object.
Error Contains an error number.

All these number types… I’m betting your head is swimming if you haven’t encountered this before. Have no fear… we’ll go over them more a little later. Atleast, for now you see what I’m talking about. Next time, I’ll go over conversion functions to convert number types.

Extra Credit: Think about if I had a payroll script I was working on– and you were actually going to get paid by it. You worked 40.5 hours (or if your salary your check should be $1201.62) Would you mind terribly if I fed this to the payroll department after converting these numbers to an Integer first?


Apr 2 2008   2:49PM GMT

Using Vbscript to gather server performance counter data with WMI



Posted by: Jerry Lees
VBScript, Development, Windows Management Interface, Functions, PerfMon, Performance Monitoring, WMI, Remote management

In my last entry I shared with you how to use WMI in Vbscript to reboot a server from a scheduled job (either locally or remotely) and I hinted at a scenario where I needed to use this script because a server had a memory leak in an application (Trend Micro OfficeScan 8.0, to be exact). They’ve got a fix out but we just upgraded to 8.0 and apparently that didn’t go well, plus this patch is a server patch that immediately rolls out to the clients– so they are less than willing to jump onto the razor’s edge with a patch. (Politics– We’ve all been there, right?)

 Well, in this entry I’m going to share the function I wrote to pull Poolmemory Non-Paged Bytes from the server using Win32_PerfFormattedData_PerfOS_Memory. I’ll not go into detail about this class and its functions and members here in this posting, but you can find out more details at Microsoft’s MSDN site here. Remember from a previous post (Determining properties and methods used in a WMI object for use in a vbscript), that you can always find out what properties are available by looking at the class definition of these pages.

 The function I wrote pulls the PoolnonpagedBytes property from the Win32_PerfFormattedData_PerfOS_Memory object. This function requires you to pass it the last value of the performance counter. While it doesn’t use it to get the data it does internal to the function compute the delta of the last and the new value– which is handy if your logging and/or monitoring in real time troubleshooting.

The following is a function only, not a complete vbscript to save space and to focus in on this part of the code. For a complete working example script that is tehone I’ve been talking about in the last two posts go here that combines the previous posting’s reboot function, this function, and takes into account the number of times a value can exceed a threshhold during a time frame look here in the vbscript section for “non-paged pool memory“.

Function GetMem(last)
     Set oLoc=CreateObject(”WbemScripting.SWbemLocator”)
     oLoc.Security_.ImpersonationLevel=3
     oLoc.Security_.AuthenticationLevel=WbemAuthenticationLevelImpersonation
     Set owmi=oLoc.ConnectServer(strSrv,”root\cimv2″)
     Set oRef=oWmi.ExecQuery(strQuery)

     For Each detail In oRef
         Newval = detail.PoolNonpagedBytes
         WScript.Echo Newval & vbtab & Newval-last
         getmem = (Newval/1024)/1024
     Next
End Function

Obviously, you have to do some work before you call the function setting up both a variable to recieve the return and also some sort of variable to keep track of the last value. If you aren’t after tracking the changes and only want the return value you can pass any number, including zero, to the fuction and remove the wscript.echo lines in the above code snippet.

Also, since it’s a snippet and as I write this I noticed that you will need some setup in the main routine like:

  •  a variable in your main script called strSrv that has the name of the server you want to pull the value of the counter.
  •  The following line in the main routine that sets up the “SQL” call for WMI and initializes the value of strQuery. (Btw, for a good back to basics look at SQL calls, check out the SQL Server with Mr. Denny Blog here on ITKE.)

              strQuery=”SELECT * From Win32_PerfFormattedData_PerfOS_Memory”

You can find more performance monitor classes that are available to you here. Basically, if it’s available in perfmon– you can get it with vbscript! Just look for classes named like Win32_PerfFormattedData…. or Win32_PerfRawData…, these classes will get you what you want. Keep in mind that Raw data is just that and most times you are going to want to get PrefFormatted data in the beginning. If you’d like more information on the differences, post a comment and I’ll come back to it later.

Again, this code snippet works perfectly in my original script, but sometimes when you strip a piece of code out of a script it doesn’t work right when you plant it somewhere else. Also, 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 complete original script code (and this snippet) for download for you from my website’s (www.webstemsadministration.com) File Depot under the Vbscripts and ITKE Blog Scripts category respectively.

Enjoy and happy scripting!

Extra credit: This is double extra credit, I guess, in my last entry I gave you a hint at my last extra credit question in my previous post– I just made the call a different way. The last posting asked you about what this part of the code did:

{impersonationLevel=impersonate,authenticationLevel=Pkt,(Shutdown)}

Does this help give you more information to go on?