The VBScript Network and Systems Administrator's Cafe:

Functions

May 14 2008   8:58PM GMT

Getting disk usage data with the filesystem object and the Excel.Application object in vbscript



Posted by: Jerry Lees
disk usage, system trending, Excel.Application, File System Object, FSO, Functions, Scripting.FileSystemObject, VBScript, Documentation

In my previous posting, entitled Working with the Excel.Application object in vbscript to create Excel Spreadsheets, we worked with excel in vbscript to create a excel spreadsheet. The spreadsheet wasn’t going to win any awards for complexity or usefulness, but none the less it was a spreadsheet– and more importantly it was generated by a script! I also promised to bring you a script to help you chart diskspace usage in my next posting in the series. This posting is the fulfilment of that promise! Also, please note that you will need Excel installed where the script runs for this script to operate correctly– but it does not need to be installed on the system you are pulling disk free space information from since I used the WMI object instead of teh filesystem object.

The script below uses WMI’s Win32_LogicalDisk class to grab the drives in the target system, specifically the drive you specify through the use of a where clause in the SQL statement that pulls back the WMI data. (Through the “where deviceid like” section of the SQL statement in the code)

 Also, I didn’t put a lot of effort into the code where the for/next loop is that loops through getting and saving the free space because I didn’t want to create a lot of extra complexity and wanted to create a script that would run through to completion pretty quickly. Currently, the script takes 10 minutes to complete. To test the script while it’s running, just create files in a folder and delete them a number of times. I created a 10Mb and 20Mb file and made a series of copy/pastes during execution– with a smattering of deletes in the mix.

For further customization, you can look at the code from the posting I wrote a while back Reporting CPU usage by saving it to a file with the VBScript filesystem object to get a good feel for how to modify the loop to get what you want. In essence, change the number 2 in “wscript.sleep 2″ to a lager number to get a bigger gap between samples and change the 300 in the “For x = 1 to 300″ line to a larger number to get a longer sample period.

Here is the code:
Dim Freespace, CurrentRow, ServerName
Const xlSaveChanges = 1

‘the first row in excel is 1 (not 0)
CurrentRow = 1
ServerName=”.”

Set objExcel = CreateObject(”Excel.Application”)
objExcel.Visible = False
objExcel.Workbooks.Add
For x = 1 to 300 ‘ change 300 to increase your sample duration
     objExcel.Cells(CurrentRow, 1).Value = GetFreeSpace(”C:”,ServerName)
     CurrentRow = CurrentRow + 1
     Wscript.sleep 2 ‘change this to spread out your samples
next

objExcel.ActiveWorkbook.SaveAs (”C:\excelvbscript.xls”)
objExcel.Quit

Function GetFreeSpace(Drive,strComputer)
     Set objWMIService = GetObject(”winmgmts:{impersonationLevel=impersonate}!\\”_
         & strComputer & “\root\cimv2″)
     Set colDisks = objWMIService.ExecQuery (”Select * from Win32_LogicalDisk where deviceid like “_
         &chr(34) & Drive & chr(34))
     For Each objDisk in colDisks
         GetFreeSpace = (objDisk.freespace/1024)/1024 ‘ get MB free
     Next
End Function

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, plus example output files  from my final tests for you. You’ll find the code and other files available for download from my website’s (www.webstemsadministration.com) File Depot under the ITKE Blog Scripts category. Enjoy and happy scripting!

May 9 2008   5:54PM GMT

VbScript Statements: Explaination of Select … Case



Posted by: Jerry Lees
vbscriptstatements, VBScript Statements, VBScript, Functions

The Select … Case Vbscript statement is a very powerful way to easily preform specific actions based on a comparison of a variable to a series of cases you specify, plus it allows for the fact that NONE of the cases apply with an optional case else condition. The Select Case statement is often a better solution then a if…Then…Else if when you have more than 2 conditions that could apply.

Consider the following code snippet to check if a number is positive or negative:

Function TestNumber(Number)  

    Select case Number
        Case Number > 0
             TestNumber = “Positive”
        Case Number < 0
             TestNumber = “Negative”
        Case Else
             TestNumber = “Zero”
    End Select


May 2 2008   4:15PM GMT

Easily document group policy objects in Microsoft Word using VBScript with the Microsoft.XMLDOM and Word.Application objects



Posted by: Jerry Lees
Functions, DataManagement, Microsoft.XMLDOM, VBA, VBScript, XML, Word.application, Documentation

OK, here is the posting I hinted at in  my previous posting this week entitiled, Using Vbscript to create Word documents automatically with the Word.Application Object. In that posting I mentioned a project where I had to create a ton of documentation… but I didn’t say what it was that I had to document. Yeap, you guessed it from this article’s title… Group Policy Settings! I had to document settings in a series of policies I was proposing we implement at my employer. Here is the scenario:

I was asked “Can you document all the settings you are proposing in the new policies for the other members of IT? Also, Can you document the name of the setting, what you want it to be and what options are available to change it to? Oh, and what each value means when you set it?…. Do you think you’ll have time to also let us know for each setting what the supported or intended OS version is for the setting? I need it by Friday.”

Now, much like you might do, I said “I’ll try.” and mumbled under my breath later “If you bring me a pound of Lead I’ll turn it to Gold too!”… None the less, after my initial pitty party, I began looking at the Information available to me in the Group Policy Management Console (Available here if you don’t have it already.), much to my surprise I found almost everything I needed when I looked at the individual settings… it just wasn’t in a format I could show to people or they could read easily. So I set out to try and copy and paste the information into word… for 20 seconds… and realized this is way to much work! And what do I always say??????   Be Lazy!

Now I looked at the options available to me on exporting the file and CSV was one of them, but unfortunately all the relationships were lost and I couldn’t make heads or tails of how to cobble it back together in a meaningful way after the export. Then I noticed XML and remembered my last post on Microsoft.XMLDOM (Using XML in vbscript via Microsoft.XMLDOM to work with data feeds) and thought, I really need to get back to that… so here we are!

First, Just like my last post– you’ll need Microsoft Word installed where you run this script for it to operate. Then you’ll need to use The Group Policy Management console to export the policy settings to XML. (hover over the icons along the top, it’s the one with the icon that looks like a page of paper with an arrow pointing right, one of the save as options is XML.) Save this file into the location where the script is located (I recommend a descriptive name, because it will be the heading for your document.) and with a single edit of the script you will have a word doc on the root of your C: drive with the same name— only documented in Word!

The script basically opens and reads in the XML Document and creates a Word.Application object to create a Microsoft Word Document at the root of the C: Drive, then writes formatted text to the document to make the data in the XML readable. But, enough of a introduction! On to the script! Here is the script:

 set xmlDoc=CreateObject(”Microsoft.XMLDOM”)
Set objWord = CreateObject(”Word.Application”)
Set objDoc = objWord.Documents.Add()
Set objSelection = objWord.Selection

‘This is the actual name of the XML document minus the path and the “.XML” extension, it becomes the word doc header
xmlfile = “Locked Down Desktop Policy”

objSelection.Font.Name = “Arial”
objSelection.Font.Size = “18″
objSelection.Font.Bold = True
objSelection.TypeText xmlfile & VbCrLf

objSelection.Font.Bold = False
objSelection.Font.Size = “10″

xmlDoc.async=”false”
xmlDoc.load(xmlfile &”.xml”)
for each x in xmlDoc.documentElement.childNodes
If x.nodename = “Computer” or x.nodename = “User” Then
For Each y In x.childnodes
if y.Nodename = “ExtensionData” then
For Each z In y.childnodes
If z.Nodename = “Extension” Then
For Each setting In z.childnodes
objSelection.TypeText “______________________________________” & vbCr
DocumentPolicy(Setting)
Next
End if
Next
End if
Next
End If
Next
objDoc.SaveAs(”C:\” & xmlfile & “.doc”)
objWord.Quit

Function DocumentPolicy(Setting)
‘this function basically cleans up the headers of the word document, so they are more human readable
Select Case setting.nodename
Case “q1:Policy”
replacestr = “q1:”
Case “q1:DropDownList”
replacestr = “q1:”
Case “q1:Name”
replacestr = “q1:”
Case “q1:Value”
replacestr = “q1:”
Case “q1:State”
replacestr = “q1:”
Case “q2:Audit”
replacestr = “q2:”
Case “q2:SecurityOptions”
replacestr = “q2:”
Case “q2:EventLog”
replacestr = “q2:”
Case “q2:RestrictedGroups”
replacestr = “q2:”
Case “q2:File”
replacestr = “q2:”
Case “q2:Display”
replacestr = “q2:”
Case “q3:General”
replacestr = “q3:”
Case “q3:HashRule”
replacestr = “q3:”
Case “q3:PathRule”
replacestr = “q3:”
Case “q3:InternetZoneRule”
replacestr = “q3:”
Case “q4:AutoEnrollmentSettings”
replacestr = “q4:”
Case “q4:AutoEnrollmentSettings”
replacestr = “q4:”
Case “q4:RootCertificateSettings”
replacestr = “q4:”
Case “q4:EFSSettings”
replacestr = “q4:”
Case “q5:PreferenceMode”
replacestr = “q5:”
Case “q2:PreferenceMode”
replacestr = “q2:”
Case “q2:ProxySettings”
replacestr = “q2:”
Case “q2:UseSameProxy:”
replacestr = “q2:”
Case “q2:HTTP:”
replacestr = “q2:”
Case “q2:NoProxyIntranet:”
replacestr = “q2:”
End Select
objSelection.Font.Bold = True
objSelection.TypeText VbCrLf & replace(setting.nodename, replacestr,”") & VbCrLf
objSelection.Font.Bold = False
For Each Value In Setting.Childnodes
NodeName = replace(Value.nodename,replacestr,”")
If NodeName = “Explain” Then
objSelection.Font.Bold = True
objSelection.TypeText Nodename & “: ” & vbcrlf
objSelection.Font.Bold = False
objSelection.TypeText vbTab & replace(value.text,”\n\n”, VbCrLf & VbCrLf & vbTab )& vbcrlf
Else
objSelection.Font.Bold = True
objSelection.TypeText Nodename & “: “
objSelection.Font.Bold = False
objSelection.TypeText vbtab & value.text & vbcrlf
End if
Next
If isnull(Setting.childnodes) Then
For Each node In Setting.childnodes
DocumentPolicy(node)
next
End if
objSelection.TypeText VbCrLf

End Function

Now, when you run this script agains your export there may be some XML tags I didn’t notice because a setting you set is one I didn’t set. Any time you see them in the document you can add a new Case statement in the select case followed by setting the replacestr to the string you want to replace with a null. The lines I’m talking about look similar to this:

  Case “q2:xxxxxxxx”
replacestr = “q2:”

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, plus example XML files and Generated Word Documents for you. You’ll find 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   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 teh article, take a second to go back and look it over and digest the code because this article is identicle 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
Next
Const 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 trobleshoot 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 thefile not existing and you using the append access methods, becasue 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 textfile” 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 filename 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 easliy 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 assunmes the file already exists and you will recieve 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 & ” occured.”
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 toolbelt 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, Remote management, PerfMon, Windows Management Interface, Administration tools

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 pre-formatted 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 teh pre-formatted 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 percantage 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 identicle… 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 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?


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 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!