• No results found

Working with Passing Arguments

In this lab, you’ll work with passing arguments by modifying a script that uses WMI to list all the services associated with a particular process on the machine. This is in fact a very useful script. While we are at it, we will simplify the script a little to make it eas­ ier to read.

Lab Instructions

1. Open the servicesProcess.vbs script and save it as lab7.vbs. 2. Add the Option Explicit command at the top of the script.

3. Declare each variable used in the script. This would include the following: Dim objIdDictionary Dim strComputer Dim objWMIService Dim colServices Dim objService Dim colProcessIDs Dim i

4. Save the script, and run it to ensure you have all the variables defined. If you missed a variable, Option Explicit will cause the “variable is undefined” error and list the line number containing the undefined variable.

5. Add a declaration for wmiRoot by adding Dim wmiRoot under the line that says

Dim colProcessIDs.

6. Under the line that says strComputer = ".", add the following:

wmiRoot = “winmgmts:\\” & strComputer & “\root\cimv2”

The preceding line shortens the following line: Set objWMIService = GetObject(“winmgmts:” _

& “\\” & strComputer & “\root\cimv2”)

7. Edit the Set objWMIService = GetObject line by deleting everything after the Get-

Object command. Inside the open parenthesis, type wmiRoot and add a close

parenthesis. The line should now look like the following: Set objWMIService = GetObject(wmiRoot)

What you have done is created shorthand for the long winmgmts string. In addi­ tion, you deleted some stuff you didn’t need (which we’ll discuss in detail when we talk about WMI in Chapter 5, “The Power of Many More”). The script is now much easier to read.

8. Run the script—it should work fine to this point. If it does not, compare it with lab7pt1.vbs and see where your code needs tweaking. Your script must run cor­ rectly at this point to complete the lab.

9. If everything is groovy, look at the following line: Set colServices = objWMIService.ExecQuery _

(“Select * from Win32_Service Where State <> ’Stopped’”)

You’ll make this line easier to read by placing the “Select * from Win32_Service

Where State <> ‘Stopped’” line into a variable, which we unceremoniously call

wmiQuery. To do this, you must adjust the code in two ways. First, you must declare

the variable wmiQuery by typing the following after the wmiRoot declaration:

Your second adjustment is much trickier and therefore much more critical. You must define wmiQuery to be equal to the Select statement listed in step 9. You handle this under the following line:

Set objWMIService = GetObject(wmiRoot)

To define wmiQuery, copy the Select statement from the Set colServices line, mak­ ing sure to include the quotation marks with your copy. The wmiQuery line now looks like the following:

wmiQuery = “Select * from Win32_Service Where State <> ’Stopped’”

After you add the wmiQuery line above the Set colServices line, you delete the

Select statement from the Set colServices line. In place of the Select statement, you

use the variable wmiQuery. The modified line looks like this: Set colServices = objWMIService.ExecQuery _

(wmiQuery)

10. Save the file and run the script. It should still work properly. If it does not, com­ pare it with the lab7pt2a.vbs file to see whether you can optimize your code. 11. Now you will perform the same kind of adjustments to the second half of the

script. Look at the following code (which starts around line 44): For i = 0 To objIdDictionary.Count - 1

Set colServices = objWMIService.ExecQuery _

(“Select * from Win32_Service Where ProcessID = ’” & _ colProcessIDs(i) & “‘“)

You want to put the Select statement into a wmiQuery variable. Recall from our discussion in Chapter 1, “Starting from Scratch,” that you can reuse variables whenever you want to. To illustrate this point, you will reuse the variable name

wmiQuery. You define wmiQuery to be equal to the Select statement. To do this,

you must define it prior to the line where you’ll need to use it. This will be below

the For i = 0 line and above the Set colServices line. After you do this, you replace

the Select statement with the variable wmiQuery. The modified code looks like the

following:

For i = 0 To objIdDictionary.Count - 1

wmiQuery = “Select * from Win32_Service Where ProcessID = ’” & _ colProcessIDs(i) & “‘"

Set colServices = objWMIService.ExecQuery _ (wmiQuery)

12. Run your script. If it does not run, compare it with lab7pt3.vbs.

13. One aspect of your script that you might find annoying is that it doesn’t indicate when it is finished running. Let’s fix this by adding a WScript.Echo command to let us know the script is done. You just do something like the following:

14. To modify the script to accept a command-line argument, simply edit strComputer

= “.” so that the variable strComputer is assigned to be whatever comes in from the

command line, not ".", which means this local computer. The revised line looks like the following:

strComputer = WScript.Arguments(0)

By doing this, you now will run the script against any computer whose name is placed on the command line at the time you run the script.

15. Save your script. You can compare it with lab7pt4.vbs. To run the script, go to the directory where you have been saving your work, and open a command prompt. You will want to run the script under CScript, and you will need to include the name of a reachable computer on your network. The command line for mine looks like this:

C:\scriptingBook\ch4\lab7>cscript lab7pt4.vbs s1

16. What happens when you try to include two server names? What happens when you try to run the script without a command-line argument? Let’s now modify the script so that it will provide a little bit of help when it is run. As it stands now, when the script is run without a command-line argument, you simply get a “sub- script out of range” error. In addition, when you try to include several computer names from the command line, the first one is used and the others are ignored. 17. To add some help, check to ensure that the person running the script added a com­

mand-line argument when they executed the script. To do this, check

WScript.Arguments.UnNamed.Count and make sure it is not zero. Use an

If…Then…Else construction to perform this check. This construction needs to fol­

low the Header information section of the script. The code looks like the following: If WScript.Arguments.UnNamed.Count = 0 Then

WScript.Echo(“You must enter a computer name”) Else

18. Since you’re using an If...Then...Else construction, you must end the If statement. To do this, simply place the command End If at the bottom of the script. The script to this point is saved as lab7pt5.vbs.

19. Now use the Split function so that you can enter more than one computer name from the command line. Doing this will be a little tricky. First you must declare two new variables, listed here:

Dim colComputers Dim computer

Because strComputer is used to hold the command-line arguments, and you want to be able to run the script against multiple computers, you’ll need to be able to hold a collection of names. ColComputers is used to hold the collection of com­ puter names you get after you parse the command-line input and “split” out the

computer names that are separated by commas. Since you now have a collection, you have to be able to iterate through the collection. Each iterated item will be stored in the variable computer.

20. Under the strComputer = WScript.Arguments (0) line, add the colComputers line in which you use the split command to parse the command-line input. Then use a

For Each line to iterate through the collection. The two new lines of code are

listed here:

strComputer = WScript.Arguments(0) colComputers = Split(strComputer, “,”)

For Each computer In colComputers

21. Because you’re modifying the input into the script, you need to change your

wmiRoot statement so that it points to the parsed line that comes from the split

command. To do this, you use the following line of code just after the For Each

command in the colComputers line:

wmiRoot = “winmgmts:\\” & Computer & “\root\cimv2”

22. Add an additional Next statement near the end of the script. Since you are doing

a For Each Next construction, you need to add another Next command. The bot­

tom section of the script now looks like the following: For Each objService In colServices

WScript.Echo VbTab & objService.DisplayName Next

Next Next

WScript.Echo “all done" End If

The script starts to get confusing when you wind up with a stack of Next com­ mands. You might also notice that in the lab7pt6.vbs script, I indented several of the lines to make the script easier to read. If you’re careful, you can use the Tab key to line up each For Each command with its corresponding Next command. 23. Save your script, and try to run it by separating several computer names with a

comma on the command line. Compare your script with mine, which is saved as lab7pt6.vbs.

You’ve completed Lab 7. For extra credit, you might want to consider the following modifications: improve the spacing between runs of the script when it is run against other computers. Include the name of the computer at the beginning of each listing.