Previous Page
Next Page

Moving Past Dull Arrays

I will admit the previous two scripts were pretty dull. But because the construction of an array is very finicky, I wanted you to have a reference for the basic array (you will need it for your labs).

In the next script (ArrayReadTxtFile.vbs), you open up a text file, parse it line by line, and write the results into an array. You can use this line-parsing tactic later as a way to feed information into a more useful script. Right now, all you're doing with the array after it is built is echoing its contents out to the screen.

ArrayReadTxtFile.vbs

Option Explicit
'On Error Resume Next
Dim objFSO
Dim objTextFile
Dim arrServiceList
Dim strNextLine
Dim i
Dim TxtFile

TxtFile = "ServersAndServices.txt"
Const ForReading = 1

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile _
  (TxtFile, ForReading)
Do Until objTextFile.AtEndOfStream
  strNextLine = objTextFile.Readline
  arrServiceList = Split(strNextLine , ",")
  WScript.Echo "Server name: " & arrServiceList(0)
  For i = 1 to UBound(arrServiceList)
    WScript.Echo vbTab & "Service: " & arrServiceList(i)
  Next
Loop
WScript.Echo("all done")

Header Information

The Header information section of your script incorporates the standard bill of fare. You use Option Explicit to ensure all variables are specifically declared, which prevents the misspelling of variable names during the development phase of the script. On Error Resume Next is a rudimentary error suppression command that tells VBScript to skip a line containing an error and proceed to the next line in the script. This is best turned off during development. After using On Error Resume Next, you declare six variables. The first variable, objFSO, is used to hook the file system object (which allows you to access files and folders from the script). The next variable, objTextFile, is used as the connection to the text file itself. The variable arrServiceList is used to refer to the array of services and servers that you build from the text file. The variable strNextLine holds the text of the next line in the text file. The i variable is simply a counter that gets incremented on each loop through the text file. The last variable is TxtFile. It holds the location inside the file system that points to the specific text file with which you will work.

Option Explicit
'On Error Resume Next
Dim objFSO
Dim objTextFile
Dim arrServiceList
Dim strNextLine
Dim i
Dim TxtFile

Reference Information

The Reference information section of the script is used to point certain variables to their required values. These will be a listing of servers in column 0 and service names in the remaining columns. The text file used as input into the array is defined with the variable TxtFile. By using a variable for input into ArrayReadTxtFile.vbs, you make changing the location of the file easy. The ServersAndServices text file needs only to be defined in this location, and the variable TxtFile is left untouchedwherever it might be used within the script. The constant ForReading is set to 1, which tells VBScript that you are going to read a text file (as opposed to write to the file).

TxtFile = "ServersAndServices.txt"
const ForReading = 1

Worker and Output Information

In the Worker and Output information section of ArrayReadTxtFile.vbs, you're finally going to settle down and do something worthwhile. You must first connect to FileSystemObject to be able to read the text file. You do this by using the variable objFSO. You set objFSO to be equal to the object Scripting.FileSystemObject. Once you have created the file system object, you define the variable objTextFile to be the result of opening TxtFile so that you can read it. ObjTextFile will contain textStreamObject at this point.

To work with the array, you need to implement some type of looping construction. This is where Do Until...Next excels. You defined objTextFile to hold the text stream object that came back from opening the ServersAndServices text file so that you could read the file. Because you can look inside and read the file by using objTextFile, you now say that you'll continue to read the file until you reach the end of the stream of text. This is a most excellent use of Do Until...Next. What is the script going to do until it reaches the end of the text file? It's going to read each line and assign that line of text to the variable strNextLine. After it's made that assignment, it will look for commas and then split the text up into pieces that are separated by those commas. Each piece of text will then be assigned to your array. You're still using a single dimension array. (A single dimension array is an array that is like a single column from a Microsoft Excel spreadsheet.) Interestingly enough, you're actually creating a new array every time you use the Split function.. The nice part is that you can include as many services as you need to use by adding a comma and the service on the same line. Once you go to another line in the text file, you have a new array.

The array portion of ArrayReadTxtFile.vbs is not really created until you get to the Worker and Output information section of the script. In the Header information section, when you declared the variable arrServiceList, you really didn't know whether it was a regular variable or something else. This is why it was given the prefix arrit sort of looks like array (and requires less typing). You could have just as easily called it arrayServiceList, but doing so would have made your script longer. When you use the suffixes (0) and (i) in the WScript.Echo statement, VBScript knows you want to refer to elements in the array. The Worker and Output information section of the script follows:

Do Until objTextFile.AtEndofStream
  strNextLine = objTextFile.Readline
  arrServiceList = Split(strNextLine , ",")
  WScript.Echo "Server name: " & arrServiceList(0)
  For i = 1 To UBound(arrServiceList)
    WScript.Echo "Service: " & arrServiceList(i)
  Next
Loop

What Does UBound Mean?

Did you notice that I didn't explain the For...Next construction embedded in the Do Until loop? The goal was to make ArrayReadTxtFile.vbs as flexible as possible, and therefore I didn't want to limit the number of services that could be input from the text file. To make sure you echo through all the services that could be listed in the ServersAndServices text file, you need to use the For...Next loop to walk through the array. You can find out how many times you need to do For...Next by using UBound. Think of UBound as standing for the upper boundary of the array. As you might suspect, because there is an upper boundary, there is also a lower boundary in the array, but because the lower boundary is always zero, LBound isn't needed in this particular script.

When you run ArrayReadTxtFile.vbs, the i counter in For i = 1 To UBound(arrServiceList) changes with each pass through the list of services. To track this progress, and to illustrate how UBound works, I've modified the ArrayReadTxtFile.vbs script to echo out the value of UBound each time you read a new line from the ServersAndServices text file. The modified script is called ArrayReadTxtFileUBound.vbs and is located in the Chapter 4 folder. Its Worker section follows:

Do Until objTextFile.AtEndofStream
  boundary = UBound(arrServiceList)
  WScript.Echo "upper boundary = " & boundary
  strNextLine = objTextFile.Readline
  arrServiceList = Split(strNextLine , ",")
  WScript.Echo "Server name: " & arrServiceList(0)
  For i = 1 To UBound(arrServiceList)
    WScript.Echo "Service: " & arrServiceList(i)
  Next
Loop

To track changes in the size of the upper boundary of the array by looking at the value of UBound, it was necessary to assign the value of our new variable boundary after the Do Until command but prior to entry into the For...Next construction. At this location in the script, the new line of text has been read from the ServersAndServices text file, and the script will continue to track changes until it reaches the end of the file.

Quick Check

Q.

How did we declare an array in the previous example?

A.

We declared a regular variable, using the Dim command.

Q.

How can the population of an array be automated?

A.

You can automate the population of an array by using the For...Next command.

Q.

If you do not know in advance how many elements are going to be in the array, how can you automate the population of an array?

A.

You can automate the population of an array with an unknown number of elements by using the For...Next command in conjunction with UBound.


Combine text file array and WMI

1.
Open the \My Documents\Microsoft Press\VBScriptSBS\ch04\ArrayReadTxtFile.vbs script in Notepad or your preferred script editor. Save the script as YourNameArrayReadTxtFileCheckServices.vbs.

2.
In the Reference section of the script, change the value of TxtFile to point to "RealServers AndServices.txt". It will look like the following:

TxtFile = "RealServersAndServices.txt"

3.
Declare a new variable, boundary, in the Header section of the script.

4.
In the Worker section, arrServiceList is an array that is created by using the Split function on strNextLine. Assign boundary to be equal to UBound(arrServiceList). This goes on the line following the Split function, and it looks like the following:

boundary = UBound(arrServiceList)

5.
Following the assignment of boundary, assign strComputer to be equal to element 0 of the arrServiceList.

strComputer = arrServiceList(0)

6.
Modify the WScript.Echo line so that it informs users the output is a listing of service status messages on the computer. My Echo command looks like the following:

WScript.Echo "Status of services on " & strComputer

7.
Define a new subroutine called subCheckWMI. Do this at the bottom of your script. Begin the construction with the word Sub followed by the name of the subroutine, as seen below:

Sub subCheckWMI

8.
Skip a few lines and end the subroutine with the End Sub command, as seen below:

End Sub

9.
Open the CheckServiceStatus.vbs script from the Chapter 4 folder and copy everything but the variable declarations between the Sub subCheckWMI and End sub lines. It will look like the following when you are done:

Sub subCheckWMI
strComputer = "."
serviceName = "spooler"
wmiRoot = "winmgmts:\\" & strComputer & "\root\cimv2"
wmiQuery = "win32_service.name=" & funFIX(serviceName)

Set objWMIService = GetObject(wmiRoot)
Set objItem = objWMIService.get(wmiQuery)
         WScript.Echo vbTab & (serviceName) & " Is: " _
         & objItem.state & " startup mode is: " & objItem.StartMode
End sub

10.
Clean up the subroutine. Delete the strComputer = "." line because the value of strComputer is assigned via the text file.

11.
Delete the serviceName = "spooler" line because it will be assigned via the text file as well.

12.
Move the Set objWMIService = GetObject(wmiRoot) line under the wmiRoot line and above the wmiQuery line.

13.
The subroutine now looks like the following:

Sub subCheckWMI
wmiRoot = "winmgmts:\\" & strComputer & "\root\cimv2"
Set objWMIService = GetObject(wmiRoot)
wmiQuery = "win32_service.name=" & funFIX(serviceName)

Set objItem = objWMIService.get(wmiQuery)
         WScript.Echo vbTab & (serviceName) & " Is: " _
         & objItem.state & " startup mode is: " & objItem.StartMode
End sub

14.
Use For...Next to walk through the array that contains the service names to inspect. Place it on the next line after Set objWMIService = GetObject(wmiRoot) The line of code will look like the following

For i = 1 to boundary

15.
On the last line before the End sub line, add the Next statement to close out the For...Next loop.

16.
As we walk through the array, we want to pick up the names of the services. Under the For i = 1 to boundary line, assign the element from the array to the variable serviceName, as seen below:

serviceName = arrServiceList(i)

17.
Now that the subroutine is complete, go back to the main script and add the line to call the subroutine. It goes on the line after we print out the status of services on strComputer, as seen below:

WScript.echo "Status of services on " & strComputer
        SubcheckWMI

18.
On the line after the one that calls the subroutine, add a command to print out a blank line. I used the following code:

WScript.Echo vbNewLine

19.
Go back to the CheckServiceStatus.vbs script. Copy the function from the bottom of that script and paste it into the bottom of your script. The function looks like the following:

Function funFIX(strIN)
   funFIX = "'" & strIN & "'"
End Function

20.
Save and run the script. It should work without error. If there is a problem, compare your script with the \My Documents\Microsoft Press\VBScriptSBS\ch04\ArrayReadTextFileCheckServices.vbs script.


Previous Page
Next Page