Scripting Windows Management
On This Page
Learn how to script to work more efficiently
This article is from the April 2002 issue of Windows & .NET Magazine.
Scripting Windows management is one of those good ideas that you might not have gotten around to trying yet. Perhaps you're not sure what you could accomplish with a script that you can't accomplish from the graphical interface. Perhaps you're worried about the learning curve—you don't know whether the time scripting saves you would make up for the time you spend learning to use it.
Or maybe you're a little lost in the crowd of scripting TLAs and vocabulary—WSH, WMI, ADSI, objects, methods, procedures, functions. If you've stuck scripting in the mental Developer Stuff box to be safely ignored, you're not alone.
However, ignoring scripting might be a mistake. In fairly short order, you can learn to script well enough to save yourself time and effort. And the more you script, the more time and effort you'll save.
In this column, I explain when you should use scripting, introduce some basic scripting concepts, and provide some helpful tips (see the sidebar "Quick Scripting Tips"). In subsequent columns, I'll provide VBScript code that performs a common task and walk you through the code. I've chosen VBScript because Windows includes support for it. Windows also comes with JScript, but using one language for all the code samples will let you build on what you've learned in previous months.
The tasks I've already identified for forthcoming scripts are mostly from reader queries. I encourage you to send me your questions, with a couple of caveats: This column can't provide scripts for every occasion, and I can't provide extensive debugging support through email. However, some very smart people hang out at http://www.winscriptingsolutions.com; I recommend that you use this site's forum for getting and sharing debugging tips.
Quick Scripting Tips
Let's review a few general tips for scripting in VBScript. Future columns will include more specific tips that apply to the topic I discuss in the column, but these general tips will always apply.
Keep the lines in your scripts short. Short lines are easier to read. VBScript lets you use underscores to break lines, and statements such as If ...Then ... Else let you list conditions instead of crowding everything on one line.
Comment liberally. You know now what the statement you typed means. But will you remember what it means 6 months from now? Will someone else reviewing your code understand it? Make sure by spelling out what the pieces of the script do.
Mix case in your code. The mixed-case oDiskSpace is easier to read than lowercase odiskspace or uppercase ODISKSPACE. VBScript is case insensitive for most purposes (one exception is when you're computing the ASCII character values for letters: Uppercase letters have ASCII values different from lowercase letters).
When using Windows Script Host (WSH), use the command-line environment. WSH has two execution environments: a command-line one and a graphical one (the default). In the command-line environment, output appears in a command window unless you specifically send it to a dialog box. In the graphical environment, all output goes to message boxes. You'll want to use the command-line environment most of the time. Some operations won't work in a graphical environment, and if your script produces several lines of output, each line will have its own message box that will halt the script's execution until you click OK. To execute scripts in the command-line environment, you have two options: Preface each command you run with cscript, for example
or make the command line the default execution environment by typing
wscript //h:cscript //s
Name variables according to the kind of data they represent (e.g., give strings names that begin with the letter s and objects names that begin with o). This practice makes debugging code easier. Some expressions won't work or will work differently with data of an unexpected data type. And if you know what data type you intended to feed a script, unraveling type-mismatch errors is easier.
Explicitly define variables up front. Although you can implicitly define variables by just assigning them values in the body of the script, use an Option Explicit statement at the beginning of the script to announce that only explicitly declared variables are permissible, then declare with a Dim statement each variable you'll be using. Disallowing the use of undefined variables helps you catch bugs introduced by mistyping variable names.
Write scripts in a text editor. Don't write them in a word processor, then copy them to a text editor for saving. Scripts use a lot of quotation marks. If your word processor converts straight quotes to smart quotes, when you copy the script to the text editor, junk characters will replace the quotes and the script won't work.
Scripting a task takes longer than doing the task once manually, even if you're a VBScript pro and know how to tackle the problem. If you're not a pro, writing and debugging the script will take much longer than using the GUI. So why script?
The key application for administrative scripting is automating repetitive tasks. If you have a task that you need to perform more than once or need to perform regularly, scripting that task is a good idea. Scripting such tasks lets you perform them quickly and consistently. Scripting also lets you create tools that the GUI doesn't provide.
If the GUI is time-consuming, then what about using the command-line tools that come with the OS and resource kits? Use them when you can, but Windows 2000 doesn't have command-line equivalents for every task you might want to accomplish, and some tools might not suit your situation. Batch files don't always work well in situations in which the input must change. Besides, scripting and the command-line tools aren't mutually exclusive options. You can write scripts that exploit the command-line tools while minimizing their disadvantages.
To get started, I want to define some scripting terms. You'll follow future columns much more easily if you know what a scripting host is, how the scripting host that you use can affect your script design, whether a procedure can contain an expression, and so on.
A scripting host is the operating environment for a script. Windows doesn't understand VBScript: Type a line of VBScript code at a command prompt, and you'll get an error message. When Windows encounters a file with a recognized scripting extension, the OS passes the script to the scripting host for interpretation. The scripting host interprets the script, then passes the script's message (e.g., a request for registry data) to Windows for execution.
Windows supports two scripting hosts: Microsoft Internet Explorer (IE) and Windows Script Host (WSH). The scripting host you use affects the options available to you in building your scripts. If you use WSH as the scripting host (as we'll do most often), you can use the objects WSH supports but not the ones that IE supports, and vice versa. A scripting host doesn't understand all scripts; it understands only the ones written in languages—script engines—that the host supports. Both WSH and IE natively support VBScript and JScript.
Elements of a Script
Each line in a script is a statement that tells the computer what to do next. Executable statements usually have a simple verb-object form, expressing the action and what to perform the action against. A script might also outline the conditions under which the verb-object combination applies. The scripting host interprets lines of code from left to right and top to bottom, so you can, for example, gather information in line 10 of the script, then manipulate that information in line 30. The exceptions to this rule are procedures. Procedures—functions and subroutines—are collections of statements that run only when the script calls them. When called, a procedure is executed immediately, regardless of where the procedure's code appears in the script.
The executable pieces of a script are called statements. The nonexecutable portions of a script, preceded by Rem or an apostrophe ('), are called comments and look like
Rem This is a comment
' This is a comment
Comments can appear on a separate line or as part of a line containing executable code. Comments document the script so that someone unfamiliar with the script or even with the scripting lexicon can easily tell what the script is intended to do. You can also add Rem or an apostrophe to the beginning of an executable line to disable that line for debugging purposes.
VBScript recognizes four types of data: numbers, strings, dates and times, and Boolean statements. Numbers are numbers such as 2 or 9458. Strings are any combination of characters enclosed within quotation marks, such as "fish" and "This is a string %@#^>". Date and time information must be within octothorps (i.e., pound sign—#—characters) and follow VBScript's idea of what dates and times should look like; both #16 January 1968# and #1/01/02 11:45 PM# are valid VBScript date or time values. Boolean statements are either TRUE or FALSE, as in x<x+1 = TRUE. (They don't have to be capitalized, but I find it easier to see them if they are.) You'll often use Boolean statements when testing the validity of statements.
VBScript sees all four of these data types as subsets of a larger data type, type variant, which can contain any kind of data. Thus, you don't have to tell VBScript what type of data you're feeding it, but you also can't perform some tasks possible with languages such as Visual Basic (VB), which treat these four data types differently. (Don't worry too much about any such limitations—you might never run into them.) Groups of like data treated together are called arrays.
To simplify data manipulation, VBScript supports two other data types that have no starting value (i.e., they are null) but are assigned one in the course of a script: variables and constants. Variables can (and frequently do) change value in the course of the script while retaining the same name. Constants have one value for the duration of the script and can't be changed.
You can make data available to scripts in several ways. One way is to hard-code the data in the script. For example, coding ""\\bigserver\sharedfolder"" is a valid way of including path information in a script. Another way is to have the person running the script explicitly provide the data or provide input that tells the script to use certain data. The script can also create its own data (e.g., by calculating the date 2 weeks from today's date), then work with it.
One way to manipulate data is with operators, symbols typically used to represent mathematical functions. Some operators take precedence over others, so although VBScript typically reads lines in a script from left to right, operator precedence affects the order in which the operators are interpreted. An expression is a calculation that might include any combination of numbers, variables, strings, or constants to get some result. Expressions can include operators. For example, the expression dInputDate + 2 = dNewDate increments the variable dInputDate by 2, then assigns the new value to the variable dNewDate.
Functions and Subroutines
VBScript provides built-in functions, which let you perform certain operations without having to spell them out in expressions. With these built-in functions, you can manipulate numbers, strings, dates and times, and arrays. VBScript also has conversion functions that let you convert one type of data to another. For example, VBScript typically assumes that a number such as 45 should be the number data type, but you might want to change it to the string data type.
VBScript lets you create user-defined functions (UDFs) to perform an action that you specify in the code. For example, in
Function TestFunct TestFunct = Sqr(9) + 2 End Function
the TestFunct UDF uses the built-in Sqr function to find the square root of 9, then adds 2 to the result. You could also create a UDF that acts on arguments you feed it, just as the built-in Sqr() function accepts numbers as arguments and derives their square roots.
The TestFunct UDF produces a result that you can return to the main body of the script. A subroutine performs a predefined action that doesn't return a result to the script. The scriptwriter might put the action in a subroutine because it needs to happen many times in the course of the script and he or she doesn't want to have to retype it each time. The subroutine
Sub AskUserName WScript.Echo _ "Please type a username." WScript.Quit End Sub
exploits a couple of capabilities of the WScript object to make it print a string to the screen, then exit the subroutine. Functions and subroutines can use the values of variables declared within the main body of the script or can use variables private to themselves.
Objects in Scripting
Objects represent physical or logical parts of the computing environment, such as disk drives or user account names. You can do simple scripting without resorting to objects, but most administrative scripts use them. If you're using WSH, VBScript can use objects native to WSH, such as those representing files and folders or parts of the registry; VBScript also supports Windows Management Instrumentation (WMI) and Active Directory Service Interfaces (ADSI) objects. WMI objects represent physical and logical parts of the computing system, such as IP addresses, file systems, and network cards. ADSI objects represent resources stored in a directory service such as Active Directory (AD) or other supported directories, such as the Windows NT 4.0 SAM. Static groups of objects of the same ilk are known as classes, and user-defined groups of objects are called libraries.
Objects have properties and methods. Properties describe an object (e.g., IP Address could be a property of the Network Card object, with 22.214.171.124 being the value of that property). Methods are actions you can take against an object (e.g., Copy could be a method of the File object). Not all objects have methods. Properties and methods are both written the same way: object first, a period, then the method or property name (e.g., ObjectName.PropertyName). Objects can contain other objects. For example, the WScript object in WSH contains a subordinate WshArguments object, which is a collection of any input that the person running the script has provided. To refer in a script to the first piece of input in WshArguments, you would type WScript.Arguments(0). As you'll see when we discuss WSH objects, the formal name of the subordinate objects doesn't match the name used to invoke them in a script.
If you're new to scripting, I've probably hit you with enough information for now. In my next column, I'll begin to show you how to apply this information to building administrative scripts.
© 2002 Windows & .NET Magazine. All rights reserved.
Try a sample issue of Windows & .NET Magazine at: http://www.windowsitpro.com/sub.cfm?code=fsWI201XTN.
Windows & .NET Magazine UPDATE is a free email newsletter containing news, tips and other resources for Windows IT Professionals. Subscribe now at http://email.winnetmag.com/winnetmag/winnetmag_prefctr.asp.
We at Microsoft Corporation hope that the information in this work is valuable to you. Your use of the information contained in this work, however, is at your sole risk. All information in this work is provided "as -is", without any warranty, whether express or implied, of its accuracy, completeness, fitness for a particular purpose, title or non-infringement, and none of the third-party products or information mentioned in the work are authored, recommended, supported or guaranteed by Microsoft Corporation. Microsoft Corporation shall not be liable for any damages you may sustain by using this information, whether direct, indirect, special, incidental or consequential, even if it has been advised of the possibility of such damages. All prices for products mentioned in this document are subject to change without notice.