An object is an abstract term that scriptwriters use to represent a set of data (typically called properties) and functions (typically called methods). VBScript supports a type of object called COM objects. (VBScript 5.0 also supports another type of object called a class. My article "Creating Classes with VBScript 5.0," page 10, discusses this type of object.) COM objects are binary modules that comply with Microsoft's COM specification for building software components. You can use COM objects with any development tool that supports COM automation.
Although VBScript supports COM automation, VBScript can't use all the COM objects available through Windows. VBScript can use only those objects that expose a string called a programmatic identifier (ProgID). Although not all COM objects have a ProgID, all COM objects have a 128-bit number called a class identifier, or CLSID. If a COM object has a ProgID, you can use VBScript to instantiate the object, invoke its methods and properties, and destroy the object.
Instantiating Objects with CreateObject
When you want to use a COM object in a VBScript file, you need to create an instance of, or instantiate, that object. Instantiating a COM object is a two-part process that uses either the CreateObject or GetObject function and the Set statement.
CreateObject takes in the ProgID of the object you want to use and returns a reference to an instance of that object. For example, if you want to use the COM object FileSystemObject (FSO) to gain access to local file-system elements (e.g., files, directories), you specify
CreateObject _ ("Scripting.FileSystemObject")
where "Scripting.FileSystemObject" is the ProgID of the FSO object.
In VBScript 5.0, CreateObject can accept a second optional argument: the Uniform Naming Convention (UNC) name of the server on which the object resides. This new feature lets you create local instances of objects whose binary files reside on different machines.
To use the instance that CreateObject references, you must assign that instance to a variable. In VBScript, you can't use the assignment (=) operator for objects, so you need to use the Set statement. For example, to assign CreateObject's instance of the FSO object to the objInst variable, you specify
Set objInst = CreateObject _ ("Scripting.FileSystemObject")
This Set statement creates a reference between the objInst variable and the existing FSO object.
To make sure a variable's instance is valid, you can use the IsObject function. This function takes one argument: the variable containing the instance you want to validate. IsObject returns the value of True if the instance references a valid object or the value of False if the instance is referencing an invalid object.
You can use IsObject with an If...Then...Else statement to stop the script's execution if the instance is invalid:
Set objInst = CreateObject _ ("Scripting.FileSystemObject") If Not IsObject(objInst) Then WScript.Quit End If
Or, you can use IsObject with the If...Then...Else and On Error Resume Next statements to create code that sends you a message when an instantiation fails but doesn't stop the script's execution. For an example of this code, see Listing 2 in my September column "Understanding VBScript: Statements."
Using IsObject to check the success of an instantiation isn't always the best approach. For example, suppose you set the objInst variable to the standard null object Nothing in the code
Set objInst = Nothing Set objInst = CreateObject _ ("Object.NotExisting") If Not IsObject(objInst) Then WScript.Quit End If
(This example also works if you set the variable to any other object.) You then use CreateObject with Set to try to instantiate a COM object. Because the ProgID you specify doesn't point to an existing object, the instantiation fails. However, when IsObject executes, it returns the result of True, despite the failed instantiation. Although the variable doesn't reference the object you want, the variable still contains a reference to a valid object (i.e., Nothing). Thus, the script will continue to run even though the variable holds an incorrect instance. The incorrect instance will, in turn, likely produce incorrect results or an error later in the script.
In this case, a better approach is to use the Is operator to compare objects. This operator returns a result of True if two variables are referring to the same instance of the same object. So, for example, if you use the code
Set objInst = Nothing Set objInst = CreateObject _ ("Object.NotExisting") If objInst Is Nothing Then WScript.Quit End If
the script stops running because the Is operator returns a result of True. In other words, the script stops running because objInst and Nothing point to the same instance of the same object—an indicator that the instantiation failed. (For more information about the Is operator, see my August column "Understanding VBScript: Operators.")
Instantiating Objects with GetObject
Like CreateObject, the GetObject function returns a reference to an instance of an object. This function has two optional arguments: the object's pathname (i.e., a full path and a filename) and the object's ProgID. Although both arguments are optional, you must specify at least one. If you omit both arguments, an error results.
If you specify the pathname to an existing file but not the ProgID, GetObject returns a reference to the object registered to handle that file. For example, the line
Set wordDoc = GetObject _ ("C:\mydocs\file1.doc")
assigns a reference to Microsoft Word's Document object (i.e., an object that represents a document opened in an instance of Word) to the wordDoc variable. Depending on the situation, you can receive references to a new instance or an existing instance of a Document object. For example, if you run the code in Listing 1 and have no instance of Word running, you receive two opened documents: C:\mydocs\file1.doc and C:\mydocs\file2.doc. If you run the code and have an instance of Word running, you receive three opened documents: C:\mydocs\file1.doc, C:\mydocs\file2.doc, and the existing instance of the Document object. If you have more than one instance running, the VBScript documentation states that you can't predict which instance you'll receive. However, my experience is that you receive the instance that has been open the longest.
If you specify the ProgID but not the pathname, the results differ depending on how you set up the arguments. If you pass an empty string as the first argument in code such as
Set wordApp = GetObject("", _ "Word.Application")
VBScript returns a new instance of Word's Application object (i.e., an object that represents the Word application). This GetObject call is equivalent to the CreateObject call
Set wordApp = CreateObject _ ("Word.Application")
If you omit the pathname argument but leave the comma
Set wordApp = GetObject _ (, "Word.Application")
VBScript returns an existing instance of the Application object if one exists.
Although GetObject and CreateObject can produce the same results, they serve different purposes. If you need to create a new instance of an object, use CreateObject. If you need to reference an existing instance of an object, use GetObject. For example, suppose you have a script that adds a Word document to the queue of an application for further processing. You use CreateObject to initially create a reference to an instance of the Document object. Later, when you call that object for further processing, you use GetObject to reference the existing instance of that object.
Another circumstance in which you might use GetObject is when you want to create a Document object with a file already loaded. (If you want only a new instance of the object or don't need a document already loaded, use the CreateObject function.) To create a Document object with a file already loaded, you need to set both arguments of GetObject with code such as
Set wordDoc = GetObject("C:\" & _ "mydocs\file.doc", "Word.Document")
Note that the second argument must be the ProgID for the .doc file (i.e., Word.Document), not the ProgID for the Word application (i.e., Word.Application).
Adding a new document to a new or existing instance of Word doesn't necessarily cause the document to open and appear on screen. To open the document and make it visible, you need to invoke the Document object's methods and properties.
Invoking Objects' Methods and Properties
After you successfully instantiate a COM object, you can invoke that object's methods and properties. When invoking a method or property, you use the object.name notation, where object is the name of the variable and name is the name of the property or method you're calling. For example, to call the Word object's Visible property, you use the notation Application.Visible.
With this notation in mind, let's revisit the scenario of using GetObject to create a Document object with the file C:\mydocs\file.doc loaded. If you want to open that document and make it visible, you can use the code
Set wordDoc = GetObject("C:\" _ & "mydocs\file.doc", "Word.Document") Set wordApp = wordDoc.Application wordApp.Visible = True
Within Word, you can't have a document visible unless you have the Word application visible. Calling GetObject starts a new instance of Word and opens the given document. However, GetObject now returns a reference to the Document object, not the Word application. So you have to obtain the reference to the Application object and set the Visible property value to True to specify that you want it to appear.
Using the object.name notation can be cumbersome if you need to make many consecutive calls to the same object. Fortunately, VBScript 5.0 offers an alternative: the With statement. If you place the consecutive calls between the statement's With and End With clauses, you can leave off the variable name.
For example, suppose you want to create an instance of the FSO object and invoke several methods of that object. Instead of using the object.name notation in code such as
Set objInst = CreateObject _ ("Scripting.FileSystemObject") MsgBox objInst.GetFileName _ ("C:\autoexec.bat") ' Other statements calling objInst
you can use the With statement
Set objInst = CreateObject _ ("Scripting.FileSystemObject") With objInst MsgBox .GetFileName _ ("C:\autoexec.bat") ' Other statements calling objInst End With
Any item name that begins with a period evaluates to the full notation at runtime (e.g., .GetFileName evaluates to objInst.GetFileName).
Destroying variables and the instances they hold is important when you're working with out-of-process objects (i.e., objects from separate applications, such as Word or Microsoft Excel). When you call an Application object, Windows starts a new process for that application. This process remains running until you terminate it. You can terminate the process through the application's user interface (UI) or through the script you used to launch the application. The application's UI typically isn't visible because the process runs in the background. Thus, terminating the process through the script is often the best approach.
Using code to destroy an object is a two-step procedure. First, you call the Application object's Close or Quit method. Then, you set the variable that you used to reference that object to Nothing with code such as
Set objInst = Nothing
If you use in-process servers, you don't need to destroy objects. In-process servers automatically unload objects when a script terminates.
More About COM Objects
Now that you know how to use existing COM objects in VBScript code, I'll discuss one particularly useful COM object—FSO—in more depth next month. In addition, in a future column, I'll show you how to write a COM object. Typically, you use C++ or Visual Basic (VB) to write COM objects, but now a scripting technology called Windows Script Components (WSC) lets you use VBScript. If you don't want to wait to read about how WSC works, you can see my article "ASP and Windows Script Components" in Microsoft Internet Developer, December 1999.