Last month in my Scripting 101 series, I explained how to declare and initialize variables in Windows Scripting Host (WSH) scripts that you create using VBScript. This month, I discuss the most important job you perform in the script body: working with objects.
Regardless of the tasks your scripts perform, at some point you'll create and interact with objects. Whether implicitly or explicitly, all WSH scripts create objects. Understanding what an object is, what an object provides, and how to create and interact with objects is key to successfully using WSH. Although working with objects might be old hat to those of you with a Visual Basic (VB) background, quite the opposite is true for individuals with only a batch file background.
Objects vs. Utilities
WSH scripts and batch files have numerous significant differences, but none more important than the transition away from utilities and toward objects. Historically, developers used batch files to glue together system, resource kit, and third-party command-line utilities. Provided that you found utilities to support all the tasks that you wanted to perform, this approach worked fine. Unfortunately, developers often hit roadblocks along the way. If the utility the batch file called failed to provide some required option, the developer had to scour the Internet for another utility to fill the void. Sound familiar?
Figure 1 shows how Windows NT's graphical applications and utilities call Win32 APIs to run the task that the application or utility performs. Unfortunately, Win32 APIs aren't suitable for ad hoc scripts, and calling Win32 APIs from scripts is almost impossible. Therefore, NT limited scripting to the functionality that the utilities provided. This limitation led to a perception that Windows was scripting-challenged (especially compared to UNIX). In fact, the limited functionality led to a proliferation of third-party and open-source scripting tools to address the lack of Win32 scriptability.
So what's changed? As I've mentioned, part of the solution is WSH. WSH interacts with objects, specifically COM automation objects, to eliminate the need to find utilities that support all the tasks you want to perform. WSH provides a lightweight scripting environment capable of calling the same set of system services that the native NT graphical applications call.
The more significant piece of the solution pertains to the API. As Figure 2, page 164, shows, Microsoft is using COM to expose almost all system services in such a way that scripts and more traditional system programming languages (e.g., C++) call the same set of interfaces to perform a desired task. How is this standardization possible? With COM, system and application developers can develop their applications so that COM-aware scripting environments, such as WSH, can interact with and control COM-enabled services and applications.
For example, in addition to abstracting multiple and disparate directory services, Active Directory Service Interfaces (ADSI) lets scripts call the same ADSI services that the native Windows 2000 (Win2K) Active Directory (AD) management tools use. Similarly, Windows Management Instrumentation (WMI) provides COM-savvy scripts with the ability to fetch, read, and set the same set of Win32 system and performance data that Systems Management Server (SMS) 2.0 and other Web-Based Enterprise Management (WBEM)-enabled systems management applications access. You leverage these services by utilizing these COM objects in your scripts. The first step is to understand what an object is.
What Is an Object?
An object is simply a thing. Each object has a set of characteristics or attributes that describe the object and the actions it performs. Network OSs, messaging systems, applications, and programming languages generally classify objects in terms of a user, a group, a computer, a printer, a network, or an application. These entities are all objects in the IT world. Each of these objects has a set of properties that uniquely describe it. Each object might also perform an action using its methods. So in the computer world, properties describe an object, and objects use methods to perform actions.
Let's consider a user object. Properties of a user object might include username, full name, and password. A user object might use methods to create, delete, or set passwords. You must have a user object before you can interact with it, so let's take a look at how to create objects.
You might be interested to learn that WSH is a set of objects. WSH includes three primary objects: WScript, Network, and Shell. The WScript object provides the script execution environment. The Network object provides properties and methods typically associated with network and printer connections. The Shell object provides methods and properties associated with the desktop shell, environment variables, and the Registry.
Before you can access an object's methods and properties, you must first create an instance of the object. As part of the script execution environment, WScript includes two methods, CreateObject and GetObject, that you can use to create objects. Using these methods is a concept that represents a radical departure from calling utilities inside of batch files.
VBScript also provides CreateObject and GetObject as functions, which you'll generally want to use rather than the WScript methods. Using WScript's CreateObject or GetObject methods adds an additional layer of work and is slightly less efficient than using the analogous VBScript functions. WScript includes these methods to support third-party script engines that might not provide a mechanism to create objects.
Before we look at some examples, you need to be aware of a couple of exceptions to the requirement that you create the object before you use it. The first exception concerns WScript. Recall that I said every WSH script creates objects. Running a WSH script implicitly creates a WScript object. Therefore, you can call any WScript method or read any WScript property without an explicit call to CreateObject.
The VBScript Err object is the second object that WSH scripts automatically create. For more information about the VBScript Err object, see "Scripting Solutions: Scripting 101, Part 2," July 1999. Now, let's create some objects. A good place to start is with syntax and definitions.
The CreateObject function creates and returns a reference to an automation object. The function has one mandatory parameter and one optional parameter. In the code line
the mandatory two-part parameter is strApp.strObj, which identifies the name of the application or component containing the target object and the class name of the object to create. This application and object pair is also a programmatic identifier (ProgID). The optional parameter, strServerName, identifies the name of the server on which the target object resides. When supported, strServerName lets you create and interact with objects installed on remote machines. Microsoft added this feature to the CreateObject function in VB 6.0 and expects to include it in the Win2K WSH and VBScript releases.
CreateObject returns a reference to the newly created object. Typically, you assign the reference to an object variable so that you can interact with the object within your script. In the previous code line, VBScript's Set statement assigns the object reference that CreateObject returns to the objReference variable. After you obtain a valid object reference, you can invoke the object's methods and read or set the object's properties. The objects.vbs example script in Listing 1 demonstrates how to use the WScript CreateObject method and VBScript's CreateObject function.
At callout A, you can see that WScript methods (WScript.Echo) and properties (e.g., WScript.Application, WScript.Fullname) are available immediately without an explicit call to CreateObject. At callout B, the script uses WScript's CreateObject method to create a WSH Network object. In the string "WScript.Network", WScript is the application name and Network is the object name. The Set command initializes the objNetwork variable with the object reference that the CreateObject method returns. After you have a valid object reference, you can interact with the object.
For example, in callout D, the script echoes the values of the Network object's ComputerName, UserDomain, and UserName properties. As you can see at callout D, you access the object's properties using the object reference (objNetwork), followed by a dot (.) and the name of the property that you want to read. Many properties are read-only, as is the case with the Network object's three properties.
Callout C demonstrates how to create a WSH Shell object using VBScript's CreateObject function. Notice the WScript ProgID doesn't preface CreateObject. Therefore, callout C calls the VBScript CreateObject function rather than WScript's CreateObject method. In this case, WScript is the application name, Shell is now the object name, and objShell gets initialized to the object reference that CreateObject returns.
At callout E, the script invokes the Shell object's Run method. Similar to how you work with the object's properties, you invoke the object's methods using the object reference, followed by a dot (.) and the method name and any parameters that the method supports. The script's comments contain details about the different ways to invoke the Run method.
So what are some of the common objects you'll likely encounter as you venture deeper into WSH? Table 1 identifies several common application and object names that you might use with CreateObject. As you'll see next, you can also use GetObject to breathe life into scripts.
Similar to CreateObject, GetObject also returns a reference to an automation object. However, GetObject supports a slightly different set of parameters:
The brackets (\[\]) mark both parameters as optional. You can supply both parameters, but you must pass GetObject at least one of the two parameters.
The first parameter, strMoniker, identifies a persistent object that the target automation server or component understands, such as a Microsoft Excel spreadsheet file. In the case of ADSI, the moniker is one of the four ADSI namespaces: LDAP, WinNT, NDS, or NWCOMPAT. WMI's moniker is WINMGMTS.
The second parameter, strClass, is identical in terms of content and syntax to the two-part strApp.strObj ProgID that CreateObject uses. The code lines in Figure 3 are all valid forms of GetObject.
When do you use CreateObject, and when do you use GetObject? Experience has taught me to use GetObject primarily with ADSI and WMI. I use CreateObject for everything else. However, exceptions exist. Table 2 shows various scenarios in which you might use CreateObject and GetObject.
Where do you learn the details about the object's methods and properties? And how do you determine a specific object's application name, class, or object name? Your first stop should be the documentation that accompanies the technology. You'll also want to make sure you check out the Microsoft Developer Network (MSDN) Library at http:// msdn. microsoft.com/ library/default.htm. This library is also available on CD-ROM via subscription.
Now is the time to start looking for opportunities to replace those old batch files that call option-inhibited command-line utilities. As you do, recognize that learning this new object-based approach to scripting might require extra effort on the front end. The payoff will come when you realize the degree to which you're able to automate the back end. Today's Win32 platform is most certainly scriptable—and tomorrow's becomes even more so as these services and technologies converge in Win2K. Create an object, and have fun!