In this section, 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 easier to read.
1. | Open the \My Documents\Microsoft Press\VBScriptSBS\ch04\StepByStep\Services ProcessStarter.vbs script and save it as YourNameServicesProcess.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"
|
7. | The preceding line allows you to shorten the following line to read:
Set objWMIService = GetObject("winmgmts:" _
& "\\" & strComputer & "\root\cimv2")
|
8. | Edit the Set objWMIService = GetObject line by deleting everything after the GetObject 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 addition, you deleted some commands you didn't need (which we'll discuss in detail when we talk about WMI in Chapter 8, "Using WMI"). The script is now much easier to read.
|
9. | Run the scriptit should work fine to this point. If it does not, compare it with \My Documents\Microsoft Press\VBScriptSBS\ch04\StepByStep\ServicesProcessPT1.vbs and see where your code needs tweaking. Your script must run correctly at this point to complete the lab.
|
10. | If everything is working, examine closely 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 in the header section of the script:
Your second adjustment is much trickier and therefore much more critical. You must define wmiQuery to be equal to the Select statement. You place this code under the following line:
Set objWMIService = GetObject(wmiRoot)
To define wmiQuery, copy the Select statement from the Set colServices line, making 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)
|
11. | Save the file and run the script. It should still work properly. If it does not, compare it with the \My Documents\Microsoft Press\VBScriptSBS\ch04\StepByStep\ServicesProcessPT2.vbs file to see where changes need to be made.
|
12. | 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 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)
|
13. | Run your script. If it does not run, compare it with \My Documents\Microsoft Press\VBScriptSBS\ch04\StepByStep\ServicesProcessPT3.vbs.
|
14. | 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. At the bottom of the script, you just do something like the following:
|
15. | 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.
|
16. | Save your script. You can compare it with \My Documents\Microsoft Press\VBScriptSBS\Ch04\StepByStep\ServicesProcessPT4.vbs. To run the script, open a command prompt and go to the directory where you have been saving your work. 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:
\My Documents\Microsoft Press\VBScriptSBS\ch04\StepByStep>Cscript ServicesProcessPT4.vbs
localhost
|
17. | 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 "subscript 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.
|
18. | To add some help, check to ensure that the person running the script added a command-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 construction to perform this check. Put this code in a subroutine called subCheckArgs. The subroutine will go at the bottom of the script, but you will call the subroutine just after the Header section. The code for the subroutine looks like the following:
Sub subCheckARGS
If WScript.Arguments.count = 0 Then
WScript.Echo("You must enter a computer name")
WScript.quit
End If
End Sub
|
19. | Because you're using an If...Then construction, you must end the If statement. The script to this point is saved as \My Documents\Microsoft Press\VBScriptSBS\ch04\StepByStep\ServicesProcessPT5.vbs and you can use it to check your work.
|
20. | 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 strComputers
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 computer names you get after you parse the command-line input and "split" out the computer names that are separated by commas. Because 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.
|
21. | 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
|
22. | 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"
|
23. | Add an additional Next statement near the end of the script. Because you are doing a For Each...Next construction, you need to add another Next command. The bottom 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"
The script starts to get confusing when you wind up with a stack of Next commands. You might also notice that in the \My Documents\Microsoft Press\VBScriptSBS\ch04\StepByStep\ServicesProcessPT6.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.
|
24. | 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 ServicesProcessPT6.vbs.
|