Q: I'm having problems with the VBScript code in Listing 3. In this script, Array1 is a dynamic array that's populated by using Windows Management Instrumentation (WMI) to retrieve the properties of the Win32_Battery class. When I try to use the contents of this dynamic array to execute a query, I get the error message Error: Object doesn't support this property or method: 'Array1.' I've tried everything I can think of to make this script work but nothing has worked. What am I missing?
A: There are several problems in your script. Before I point out the problems and suggest a possible solution, I should take a minute to clarify what the script is trying to do for the benefit of our readers. In brief, the script is trying to use Array1 as an interpolated variable, as the code at callout C in Listing 3 shows. What does that mean? In the context of scripting languages, to interpolate means to insert the value of a variable into an expression, statement, or string. Let's look at a simple example in Perl, a scripting language that supports interpolated variables. Suppose you have the following code in a script:
my $cn = "cn=tmtowtdi"; my $user = Win32::OLE-> GetObject("LDAP:\\\\$cn,...") or die;
The snippet begins by assigning the string "cn=tmtowtdi" to the variable named $cn. Next, the code uses the value stored in the $cn variable as part of the connection string used to bind to a user object in Active Directory (AD). Notice how the $cn variable is part of the connection string. That is, the variable is embedded inside the double quoted string; there's no string concatenation or the like being used. When Perl encounters a variable name inside a double quoted string, Perl automatically inserts the variable's value at that point in the string—this is interpolation at work.
VBScript doesn't support interpolated variables. For example, the following VBScript version of the previous Perl snippet is invalid:
cn = "cn=tmtowtdi" Set user = _ GetObject("LDAP:\\cn,...")
To get this code to work in VBScript, you must break the connection string into multiple parts and use string concatenation to insert the value of cn, as this code shows:
cn = "cn=tmtowtdi" Set user = _ GetObject("LDAP:\\" & cn & ",...")
Now that you know what interpolated strings and variables are, let's take a closer look at the script in Listing 3. As I stated earlier, the script contains several errors:
- In the For Each…Next statement that callout A highlights, you use the variable i.However, you didn't initialize that variable before you used it.
- The nested For…Next and For Each…Next statements after the code at callout A appear to be backward. My guess is that you're trying to loop through each item in the collection returned by Exec- Query, and for each item in the collection, echo the item's properties. As written, the script loops through the properties in the array named Array1 first, and for each property in the array, loops through the collection returned by ExecQuery.
- In the code that callout B shows, you set the wmiQuery variable to the Win32_Battery class query, obtain an instance of the WMI scripting library's SWbemServices object, then call that object's Exec- Query method to perform the query on the local computer—all inside a For...Next statement. By placing this code inside this For loop, you're repeatedly performing these actions, which isn't good scripting practice because it wastes valuable system resources. This code should go near the beginning of the script, outside any loops, so that the actions are performed only once.
- In the For Each loop at callout C, you use an interpolated variable, objItem.array1(b), which is the source of the problem that prompted your question. However, as I mentioned earlier, VBScript doesn't support interpolated variables or strings.
- The Win32_Battery class has properties of type CIM_ARRAY. However, as written, the script doesn't support properties of type CIM_ARRAY. Nor does it support properties of type CIM_OBJECT.
Based on your script, I'm guessing you're trying to create a lightweight version of Scriptomatic. As luck would have it, one already exists called Scriptomatic Lite. This tool automatically retrieves and displays the values of each property in a class. Moreover, it supports properties of type CIM_ www.winnetmag.com/windowsscripting ARRAY and gracefully handles embedded CIM_OBJECT types. On the Windows Scripting Solutions Web site, you'll find VBScript and Perl versions of the Scriptomatic Lite code I adapted for the Win32_Battery class. To download these files, go to http:// www.winnetmag.com/windows scripting, enter 43315 in the Instant- Doc ID box, then click the 43315.zip hotlink. For more information about Scriptomatic Lite, go to http://msdn .microsoft.com/library/default.asp? url=/library/en-us/dnclinic/html/ scripting01142003.asp.
The adapted Scriptomatic Lite code, though, doesn't use interpolated variables. If you're set on using them, you'll need to use Perl code similar to the code that Listing 4 shows. Note that this code doesn't handle properties of type CIM_ARRAY or CIM_ OBJECT, so you'd need to adapt it accordingly.