Hey, Scripting Guy! How Can I Retrieve All the Values in a Registry Key?

ScriptingGuy1

Hey, Scripting Guy! Question

Hey, Scripting Guy! Do you have a script that will enable me to enumerate all the values in a registry key?
— DG

SpacerHey, Scripting Guy! AnswerScript Center

Hey, DG. You know, this past weekend the Scripting Guy who writes this column went out to buy doughnuts, a process that took much longer than it should have. Why did it take so long just to buy doughnuts? Because the woman in line in front of him insisted on grilling the clerk about the nutritional value of each and every doughnut in the display case. “So,” she mused at one point. “What would you say is your healthiest option?”

Look, lady, you’re in a doughnut shop, for crying out loud; your healthiest option would be to turn tail and run. Healthiest option? Good heavens, just walking into that shop probably took a year or two off your life.

Sheesh.

Anyway, the doughnut store clerk – who was far more patient and understanding than the Scripting Guy who writes this column – recommended the Blueberry Cake. Just for the heck of it, the Scripting Guy who writes this column looked up the nutritional value of a Blueberry Cake doughnut versus a traditional glazed doughnut. (Did he do all that on company time? Um, he … doesn’t remember where, or how, he found this information ….)

Here’s what he came up with:

Blueberry Cake

Glazed

Calories

290

210

Total Fat

16 grames

10 grams

Calories From Fat

140

90

In other words, the Blueberry Cake is actually a less healthy option than the glazed doughnut. Does that mean that the clerk made an honest mistake, or was he trying to get the lady to eat a Blueberry Cake doughnut, hoping maybe that she would drop dead on the spot and then never come back in just to ask silly questions about which doughnut is the healthiest option? Beats us; all the Scripting Guy who writes this column wanted to do was get his dozen doughnuts (all cake doughnuts) and go home.

The truth is, if you’re looking for healthy options the doughnut shop is not the best place to look. Instead, the best place to look is the Script Center, where we have all sorts of healthy options, like a script that can enumerate all the values (and the values of those values) found in a registry key. Enjoy this in good health:

Const HKEY_CURRENT_USER = &H80000001

Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const REG_MULTI_SZ = 7
 
strComputer = "."
 
Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")
 
strKeyPath = "Software\Microsoft\Internet Explorer\Main"
objRegistry.EnumValues HKEY_CURRENT_USER, strKeyPath, arrValueNames, arrValueTypes
 
For i = 0 to UBound(arrValueNames)
    strText = arrValueNames(i)   
    strValueName = arrValueNames(i)

    Select Case arrValueTypes(i)
        Case REG_SZ
            objRegistry.GetStringValue HKEY_CURRENT_USER,strKeyPath, strValueName,strValue 
            strText = strText & ": "  & strValue
        Case REG_DWORD
            objRegistry.GetDWORDValue HKEY_CURRENT_USER,strKeyPath, strValueName, intValue    
            strText = strText & ": "  & intValue
        Case REG_MULTI_SZ
            objRegistry.GetMultiStringValue HKEY_CURRENT_USER,strKeyPath, strValueName,arrValues  
            strText = strText & ": "
            For Each strValue in arrValues
                strText = strText & "   " & strValue 
            Next  
        Case REG_EXPAND_SZ
            objRegistry.GetExpandedStringValue HKEY_CURRENT_USER,strKeyPath, strValueName,strValue    
            strText = strText & ": "  & strValue
       Case REG_BINARY
            objRegistry.GetBinaryValue HKEY_CURRENT_USER,strKeyPath, strValueName,arrValues    
            strText = strText & ": "
            For Each strValue in arrValues
                strText = strText & " " & strValue 
            Next  
        End Select 

    Wscript.Echo strText
Next

So how does that script, useful as it might be, make you healthy? Hey, what do we look like: doctors? We can’t explain how the script makes you healthy; it just does.

Or at least it doesn’t making you any less healthy.

As far as we know, anyway.

You know what? Let’s set all this medical mumbo-jumbo aside for a moment and see if we can figure out how this all works. As you can see, we start out by defining a whole bunch of constants. We’ll use HKEY_CURRENT_USER to tell the script which registry hive we want to work with; we’ll use the other constants to determine the data type of the individual registry values we run into. For example, in WMI a registry value that has a data type of 1 happens to be a value with the REG_SZ data type. Consequently, we assign the value 1 to the constant REG_SZ:

Const REG_SZ = 1

Seems reasonable – and healthy – enough, doesn’t it?

After defining all our constants we next connect to the WMI service on the local computer. And yes, we can run this very same script against a remote computer; all we have to do is assign the name of that remote machine to the variable strComputer:

strComputer = "."

While we’re at it you should take a closer look at our WMI connection string:

Set objRegistry = GetObject("winmgmts:\\" & strComputer & "\root\default:StdRegProv")

Keep two things in mind when it comes to this connection string. First, note that we connect to the root\default namespace. That’s a little unusual; when writing WMI scripts we typically connect to the root\cimv2 namespace. Note also that we bind directly to the StdRegProv class; that’s because all the registry methods are “static” methods, which means that they operate against the class as a whole rather than individual instances of the class.

Note. Don’t worry too much about all that. We’re just trying to show off a little. Speaking of which, did you know that in 1998 Winchell’s Doughnuts created a doughnut that weighed over 5,000 pounds, and measured 95 feet in diameter? Sadly enough, however, this doughnut never made it onto the regular menu.

After we connect to the WMI service we use this line of code to assign the desired registry path (within the HKEY_CURRENT_USER hive) to a variable named strKeyPath:

strKeyPath = "Software\Microsoft\Internet Explorer\Main"

As soon as that’s done we can use the EnumValues method to retrieve a collection of all the registry values found within that registry key:

objRegistry.EnumValues HKEY_CURRENT_USER, strKeyPath, arrValueNames, arrValueTypes

This is the part where things start to get a little goofy. To begin with, we need to note that the EnumValues method will return the names and data types of all the values found in a given registry key. (But not the values found in any subkeys of that registry key; you’ll have to write a recursive function to do that.) For example, our sample script will tell us that the Main registry key includes a registry value named Anchor Underline, and that Anchor Underline has a data type of REG_SZ. That’s cool, but is Anchor Underline set to yes, or is Anchor Underline set to no? Well, that’s something EnumValues won’t tell us. We’re going to have to figure that out for ourselves.

But don’t despair; as long as we know the value names and data types figuring out the actual values isn’t too terribly difficult. (A little cumbersome, perhaps, but not too terribly difficult.) You might have noticed that when we called EnumValues we supplied the method with four parameters:

HKEY_CURRENT_USER, the constant that tells the script which registry hive to work with.

strKeyPath, the variable that tells the script which registry key to work with.

arrValuesNames, an “out” parameter that EnumValues will fill with the names of each value found in the registry key. An out parameter is simply a parameter that holds data returned by a method. We give EnumValues a variable name, and EnumValues returns the names of all the registry values and assigns that information to our out parameter.

arrValueTypes, another out parameter, this one designed to hold the data types of each value found in the registry key.

So what do we do with all the information returned by EnumValues? Well, to begin with, we set up a For Next loop that walks us through the array of value names (arrValueNames):

For i = 0 to UBound(arrValueNames)

Inside that loop, we take the name of the first registry value and assign it to a pair of variables:

strText = arrValueNames(i)   
strValueName = arrValueNames(i)

We’re going to use the variable strText to hold both the name of each registry value and – as soon as we’ve retrieved it – the value of each registry value. Meanwhile, we’ll use strValueName to represent this particular value when we try to retrieve, well, the value of that value.

Note. Is it possible to use the word value more times in a single sentence? Let’s hope not.

Any time we need to read from the registry the Scripting Guys always use WMI rather than Windows Script Host. Why? Well, it’s not because WMI is easier to use; in fact, WMI is considerably more difficult to use than WSH. That’s because WMI requires you to use a different method for each registry data type. Have a value with the data type REG_SZ? Then you need to use the GetStringValue method. Have a value with the data type REG_DWORD? The you need to use the GetDWORDValue method. By contrast, WSH enables you to read any data type using a single method: RegRead.

So then why do we always use WMI rather than WSH? One reason and one reason only: WMI lets us read the registry off a remote computer. WSH doesn’t allow for that.

At any rate, the fact that, with WMI, different data types require different methods explains this next line of code:

Select Case arrValueTypes(i)

What we’re doing here is examining the data type of the first registry value. Let’s assume that this value has the data type REG_SZ (remember, we defined a constant named REG_SZ way back at the beginning of the script). In that case, we’re going to use the GetStringValue method to read the value from the registry and then add the value to the variable strText:

Case REG_SZ
    objRegistry.GetStringValue HKEY_CURRENT_USER,strKeyPath, strValueName,strValue
       strText = strText & ": "  & strValue

Needless to say, if our value has a different data type then we’ll use a different method. You might note as well that both GetMultiStringValue and GetBinaryValue return data in the form of an array. That means we need to set up a For Each loop to get at all the values in that array:

Case REG_MULTI_SZ
    objRegistry.GetMultiStringValue HKEY_CURRENT_USER,strKeyPath, strValueName,arrValues  
    strText = strText & ": "
        For Each strValue in arrValues
            strText = strText & "   " & strValue 
        Next

After echoing back the value of strText, it’s back to the top of the loop, where we repeat the process with the next name in the array arrValueNames. When all is said and done we should have output that looks something like this:

NoUpdateCheck: 1
NoJITSetup: 1
Disable Script Debugger: no
Show_ChannelBand: No
Anchor Underline: yes
Cache_Update_Frequency: Once_Per_Session
Display Inline Images: yes

Etc., etc.

That should do it, DG; let us know if you have any questions. Incidentally, did you notice that researchers have now decided that the old maxim that everyone should drink 8 glass of water each day no longer, well, no longer holds any water? According to an editorial in the Journal of the American Society for Nephrology (of course we subscribe to this; doesn’t everybody?) this misconception is due, in part, to a misreading of a 1945 report from the Food and Nutrition Board, which stated:

A suitable allowance of water for adults is 2.5 liters daily in most instances. An ordinary standard for diverse persons is 1 milliliter for each calorie of food. Most of this quantity is contained in prepared foods.

If you read all three sentences in that paragraph you’ll see that you can get most of your daily allowance of water just by eating. But, Americans being Americans, who could be bothered to read all three sentences? People had a tendency to read just the first sentence and ignore the rest. Thus was born the myth that people need to drink 8 glasses of water a day.

Note. OK, so there’s actually a little more to the story than that, but we can’t be bothered to write down all the details. Hey, what do we look like: professional writers?

So why do we mention the 8-glasses-of-water-a-day thing? Well, health care practitioners were wrong when they said we needed 8 glasses of water a day. So does that mean that, instead of 8 glasses of water, we’re supposed to have 8 doughnuts a day? Let’s just say that the Scripting Guys are keeping our fingers crossed.

Well, OK: keeping our pudgy fingers crossed.

0 comments

Discussion is closed.

Feedback usabilla icon