The Windows registry contains data of different types. The set of supported data types is larger than most people realize. As Table 1, page 6, shows, the registry's programming interface accepts 12 data types. This set is significantly larger than most people need. In most cases, you need only three data types: strings (REG_SZ), 32-bit integers (REG_DWORD), and binary streams (REG_BINARY). In addition, two more data types are worth mentioning, even though they're infrequently used. These data types are multiple strings (REG_MULTI_SZ) and expandable strings (REG_EXPAND_SZ). Before I discuss how these data types differ, let's look at how you typically handle them in scripts.
Accessing and Manipulating Data Types
To identify the registry's data types in code, you use the names I've listed in the first column of Table 1. If you use Windows Script Host (WSH) to access the registry, you can use only the REG_BINARY, REG_DWORD, REG_EXPAND_SZ, and REG_SZ data types. This limitation is intrinsic to the RegRead, RegWrite, and RegDelete methods of the WshShell object that WSH exposes to work with the registry. If you use another set of COM objects to access the registry, you can use more data types.
The system module in charge of registry manipulation stores the data type for each registry entry in a separate location. The system returns the data type to callers (i.e., code, scripts, or applications that make requests, or calls) reading the registry. However, when you use VBScript and WSH, the WSH methods hide the data type because VBScript considers all variables Variants. Hence, the data type doesn't matter. (For more information about Variants, see "Understanding VBScript," June 1999.)
In the registry, each piece of information is associated with a node or an entry name, holds a value, and is assigned security rights and a modification date. The registry is extremely passive. When a caller asks for data about a certain entry, the registry returns the requested data without manipulating it. However, the various object models used to access the registry typically offer ways to manipulate the data to make it easier to work with. The WSH object model is no exception. The "Expandable Strings" section gives an example of registry passivity and how the WSH object model lets you rectify the situation.
The WshShell object's RegWrite and RegRead methods let you write to and read from the registry, respectively. The code in Listing 1 shows an example of how to use RegWrite. This code creates an instance of the WshShell object, then uses that object's RegWrite method to write the entry DinoE to the HKEY_CURRENT_USER\Test\MyName subkey. This entry has the REG_ SZ data type (i.e., a string).
The code in Listing 2 shows how you can use RegRead to read the entry in the HKEY_CURRENT_USER\Test\MyName subkey. When you use RegRead, you don't need to specify the entry's expected data type. In any registry node, the default entry's data type is REG_NONE. You can change this default by assigning the node's (Default) entry a specific data type, such as REG_SZ. However, after you change the (Default) entry, you can't reassign the REG_NONE data type to it.
REG_SZ is the simplest data type because it represents a plain null-terminated string (i.e., an ASCII string terminated by the null, or 0, character). Depending on your scripting environment, the string can be Unicode or ANSI. However, if you use WSH to access the registry, you don't have to worry about whether strings are Unicode or ANSI. In WSH, you always work with ANSI strings.
REG_MULTI_SZ is the data type you use when you want to pack several strings into one registry entry. A multiple string is simply an array of null-terminated strings that are terminated by an extra null character. Typically, you use a backslash followed by a zero (\0) to specify a null character, so an entry with a multiple string might look like
Neither WSH nor Registry Editor (regedit) support REG_MULTI_SZ, so you must use Win32 Registry Editor (regedt32) to enter multiple strings in the registry. As Figure 1 shows, you use regedt32's Multi-String Editor. You place the strings you want to keep null-separated in different rows and use the Enter key to move to the next line. All strings entered in separate rows will be null-separated in the final string.
If you don't like using the Multi-String Editor, you can use Win32 API functions and wrap them with specialized COM objects so that you can exploit the Win32 API functions from within a script. However, this alternative is only for seasoned scriptwriters.
Expandable strings consist of text that can (but doesn't have to) contain unexpanded references to environment variables (e.g., %COMPUTERNAME%, %PATH%). An expandable string can be a Unicode or ANSI string, depending on whether you use the Unicode or ANSI character sets. If you use WSH, though, the expandable string is always an ANSI string.
You can store as many environment variables as you want in the expandable string. However, because the registry is passive, it doesn't automatically expand environment variables when callers read from or write to the string. For example, if you write the string %SYSTEMROOT%\Web into an entry, you receive the same string when you read that entry. The registry doesn't expand %SYSTEMROOT%.
So, why would you use expandable strings instead of plain strings? In certain situations, expandable strings are more practical than plain strings. For example, an expandable string is more practical when an application must store a full pathname in the registry but you want the pathname to be machine or user independent. Expandable strings are also more user-friendly than plain strings. For example, using the environment variable %USERPROFILE% is much handier than using a long pathname such as C:\document and settings\dino esposito\myfolder.
The code in Listing 3 shows an example of how to add a new registry entry that has the REG_EXPAND_SZ data type. In the %USERPROFILE%\MyTemp string, %USERPROFILE% represents the current user's profile subtree and MyTemp is the name of the temporary folder. Figure 2 shows the result of running the code in Listing 3.
If you want to read the entry just created, you run the code
strText = shell.RegRead _ ("HKCU\Test\MyTempFolder")
RegRead returns the unexpanded string %USERPROFILE%\MyTemp.
Although the registry doesn't automatically expand environment variables, the WSH object model's ExpandEnvironmentStrings method does. This method automatically expands a string that needs to be expanded but leaves the raw text intact. You can even pass a plain string to the method without incurring an error. So, if you use environment variables, I suggest that you always use this method to filter data you read from the registry. That way, you can make sure you always work with fully expanded strings.
Using ExpandEnvironmentStrings is easy. You just pass the string you want to expand to the method. For example, the code
MsgBox _ shell.ExpandEnvironment Strings(strText)
expands then displays the string in strText.
As Table 1 shows, the registry supports several 32- and 64-bit integers. However, if you use WSH, you can only use 32-bit integers (i.e., REG_DWORD).
The registry also supports two ways to format the bytes that make up a number: Little Endian and Big Endian. The Little Endian format stores a number from the lowest byte (hence, little end) to the highest byte. For example, the Little Endian format stores the value 0x12345678 as the binary sequence
0x78 0x56 0x34 0x12
Microsoft designed all Windows platforms to use the Little Endian format.
The Big Endian format stores a number from the highest byte (hence, big end) to the lowest byte. For example, in Big Endian format, the value 0x12345678 has the binary sequence
0x12 0x34 0x56 0x78
Some UNIX systems use the Big Endian format. Windows applications rarely use it, unless they work with connected machines that use the Big Endian format.
You can store binary data streams in the registry. A binary data stream is an array of unsigned bytes that represent a piece of information. (Unsigned bytes are a standard Windows type.) For example, on the Windows Explorer toolbar, click New on the File menu. The New submenu is configurable. You can add a new entry for a special file type you frequently create and use binary data to store the bytes that will initialize that new document.
However, Microsoft strongly discourages using binary data in the registry to avoid inflating the registry's size. Microsoft recommends that you store only small chunks of data (less than 2KB) in the registry because this crucial structure in the Windows architecture can easily become a dangerous bottleneck. Moreover, using WSH and VBScript to manipulate binary data isn't easy. Thus, as a rule of thumb, rethink your solution if you're considering storing binary data in the registry.
Now that you know the structure of the registry (which I covered in "VBScripting Solutions: The Windows Registry Structure and Tools," December 2000) and the data types in it, you're ready to start modifying its nodes. Next month, I'll show you how to safely modify the HKEY_CLASSES_ROOT node, which contains many important OS settings, such as the settings for the Wind`ows shell and Windows Explorer.