Mr. Script
Fancy Filework
Applying registration keys en masse via scripting.
- By Chris Brooke
- 07/01/2004
Our interrogation abilities become somewhat more refined as we get older.
We tend to ask more intelligent questions, such as the one I received
from Wilfredo Santiago:
Do you know of a script that would apply three
Registry keys? I have them as .REG files that I could install by putting
the file on each computer and double-clicking the .REG file on each one.
However, since I have to make this registry change on 30 systems, I would
prefer NOT to have to be going from machine to machine running them from
a floppy.
We discussed this very topic—albeit from a somewhat different perspective—in
last month’s online column (www.mcpmag.com/columns/article.asp?editorialsid=718).
So, in answer to Wilfredo’s question: “Why not?” Why not, indeed! After
all, the Registry is huge. Demonstrating different approaches for accomplishing
a variety of tasks is what makes the world go around.
In addition to taking a closer look at modifying the Registry, we’re
also going to explore a different (and arguably superior) method for getting
data out of text files: ActiveX Data Objects (ADO). In the past, whenever
we needed to pass data to a script, we would either put it into an Excel
spreadsheet and read the data using the Excel type library or put the
data into a simple text file and access it using the FileSystemObject.
Several times over the years I’ve attempted to impress upon you the power
and versatility of the FSO. "It’s worth plodding through the object model,"
I’d say. "You’ll find yourself relying on it often." That remains true.
However, on those occasions when we need to extract data from a text file,
it makes sense to do so with a tool designed for data. Enter ADO.
Without going into a great deal of detail about how ADO connections and
recordsets work, let me just say that viewing a recordset with ADO provides
increased functionality and flexibility. Why, just the power to go back
to the beginning of the recordset or to choose specific records is worth
the price of admission. That price, by the way, is free. ADO comes with
Windows—just like the FSO.
To make this point clearly, I’ve taken the script from last month and
substituted ADO for the FSO. Let’s take a look at the script and then
discuss some of the ways in which ADO has helped to improve it.
<package>
<comment>
ChangeRegKey.wsf
Change a registry entry
pointing to a resource
</comment>
<job>
<runtime>
<named
name="List"
helpstring="File
containing list of computers"
type="string"
required="true"
/>
<description>
This script changes a value
in the registry
</description>
<example>
C:\cscript ChangeRegKey.wsf /List:C:\list.txt
</example>
</runtime>
<object
id="objConn"
progid="ADODB.Connection"
Reference/>
<object id="objRS"
progid="ADODB.Recordset"
Reference/>
<script
language="VBScript">
Option Explicit
Dim objRegistry, strList
Dim strValue,
strKeyPath, strValueName
const
HKLM = &H80000002
objConn.Open
_
"Provider=Microsoft.Jet.OLEDB.4.0;"&
"Data
Source=C:\;" & _
"Extended
Properties=""text;HDR=YES;FMT=Delimited"""
strList=WScript.Arguments.Named("List")
objRS.Open
"SELECT * FROM " & strList, objConn,
_
adOpenStatic, adLockOptimistic,
adCmdText
objRS.MoveFirst
Do Until
objRS.EOF
strComputer=objRS.Fields.Item("Computer")
Set objRegistry=GetObject
_
("winmgmts:{impersonationLevel=impersonate}!\\"
_
&
strComputer & "\root\default:StdRegProv")
strKeyPath = "SOFTWARE\InventorySys\Connection"
strValueName = "ServerURL"
'Check the current
value
objRegistry.GetStringValue _
HKLM, strKeyPath,
strValueName, strValue
If strValue="URLForNewServer"
Then
WScript.Echo "Value already set."
WScript.Quit
Else
strValue="URLForNewServer"
'Write the new
value
objRegistry.SetStringValue _
HKLM, strKeyPath,
strValueName, strValue
WScript.Echo "Value
successfully changed."
End If
objRS.MoveNext
Loop
objRS.Close
objConn.Close
WScript.Quit
</script>
</job>
</package>
You should notice a few undeclared variables used when I opened the Recordset.
These are actually constants that I avoided having to declare by setting
a reference to the object (note the “reference” keyword in the <object>
tag). Don’t worry about the (apparently) convoluted code in the objConn.Open
line. Most of this is boilerplate. However, take note that we’ve added
a header labeled Computer to our list of computers in the List file. Make
sure to do this in your list, or your query will return nothing.
From a functionality standpoint, we haven’t really added a lot. The script
does the same thing it did using the FSO. However, by using ADO, we’ve
opened up a world of opportunity vis-à-vis scripting flexibility. Here
are a few examples:
- Because the text file we’re reading is a list of computers that the
script connects to, we could put in error handling to note any failed
connections and try them again before the script terminates.
- We can create a header row if the text file contains multiple columns
(such as a comma-delimited file).
- We can use these headers to filter the results by issuing SQL-style
queries: "Select * From rsList Where Completed
= 'False'" (or any other criteria). With the FSO, we’d have
to write custom logic to parse the entire line.
- We can make scripts that are interchangeable with data sources.
With the FSO, you point to a file. ADO can point to a file in a connection
string or point to a DSN (Data Source Name). If we were to change the
script to point to a DSN, then the script could remain unchanged regardless
of the data source. We discussed this “open” aspect of ODBC a bit last
month.