Learn about Windows PowerShell
Hey, Scripting Guy! How can I tell whether a value exists in the registry on a remote computer?-- AL
Hey, AL. Full disclosure time: even though we go by the name The Scripting Guys, we don’t claim to know everything there is to know about scripting. This question is a good example of that. When we first read it we thought, “Well, obviously there’s some kind of If Exists method in WMI that can do this.” Imagine our surprise when we found out there wasn’t; in fact, we couldn’t find any way to see whether or not a registry value exists. We even - gasp! - resorted to reading the documentation, thinking maybe we had missed something. No such luck.
After failing to find an If Exists method, we thought, “OK, we’ll just try to read the value. Surely trying to read a non-existent value will trigger an error. We can then trap the error, and determine that the value exists.”
As it turns out, if you use WSH’s RegRead method to read a value that doesn’t exist, an error will be triggered. Bu the RegRead method only works on the local computer; you can’t use it to read the registry on a remote computer. For that you need to use WMI. And guess what: if you use WMI to try and read a value that doesn’t exist, no error is generated. Instead, WMI keeps plugging along as if nothing had gone wrong. Crazy.
But then we noticed something. When you use WMI to read from the registry, the value is returned as an “out parameter.” When we checked the actual value of that out parameter, we discovered that any time you try to read a non-existent value, you get back a Null. That means that all we have to do is check for a Null value, and we’ll know whether or not the registry value exists.
Got all that? Here’s a sample script that looks for the registry value HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Test Value:
Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set objRegistry = GetObject("winmgmts:\\" & _
strComputer & "\root\default:StdRegProv")
strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
strValueName = "Test Value"
If IsNull(strValue) Then
Wscript.Echo "The registry key does not exist."
Wscript.Echo "The registry key exists."
As you can see, we begin by setting the constant HKEY_LOCAL_MACHINE to &H80000002; we’ll use this value to connect to the HKEY_LOCAL_MACHINE portion of the registry. We then connect to the WMI service, and to the StdRegProv class (which, as you can see, is in the root\default namespace).
After stashing the registry path and the registry value in a pair of variables, we then call the GetStringValue method. Note the four parameters for this method: our constant HKEY_LOCAL_MACHINE; the variable strPath (representing the registry path); the variable strValueName (representing the registry value we’re trying to read); and strValue. strValue is our out-parameter: the actual string value recorded in the registry will be stored in strValue and returned to us.
And that’s how we can tell if registry value exists: if strValue is Null, then the value could not be found. We tried this on a number of registry values, and it seemed to work each time. It also worked on REG_DWORD values, although - of course - you have to use the GetDWORDValue method to read one of those values. (For detailed information about how to work with the registry using WMI, check out the Registry chapter in the Microsoft Windows 2000 Scripting.)
Now, we know what you’re thinking: you’re thinking, “Ok, but what if I create a registry value and then just leave it blank? Won’t the out parameter come back as Null even though the registry value actually exists?” Believe it or not, that doesn’t appear to be the case. Instead, a blank registry value is returned as “empty;” that is, the value is equal to an empty strong (“”). And while we recognize that this can be confusing, in this case nothing (an empty string) is not the same as, well, nothing (a Null value). Empty means that the registry value exists, but is blank; Null means that the registry value doesn’t exist.
Like we said, we tried this out on a random assortment of registry values, and it seemed to work each time. If you run into situations where it doesn’t work, please let us know.
In my system I'm using WScript and the line Set objRegistry = GetObject("winmgmts:\\" & _
strComputer & "\root\default:StdRegProv")
keeps giving me an error box. Error = Expected ';' Code 800A03EC Microsoft JScript complilation error. I've tried putting it on 1 line and on 2 as shown with the same result.
Is the code different becuse of the script I'm using?
I copied your script and then substituted Test Value with an actual Key that I was looking at, it still returns "The registry key does not exist."
In regard to the "The registry key does not exist." return, are you sure the value you are looking for is a string and not a DWORD? If you are after a DWORD, substitute DWORD for String in the code ie.'GetStringValue' becomes 'GetDwordValue'
The WMI documentation page [aa390788(VS.85).aspx] states that GetStringValue is a function that returns zero for success and non-zero for failure.
I can use it in VBScript as you describe, but when using it in Excel VBA I get the error "the object invoked has disconnected from its clients" when I retrieve an item that doesn't exist.
How can I handle it if I don't know the full strValueName? Example: Determine if SQL Server is installed using this script. I know under HKLM\SYSTEM\CurrentControlSet\Services holds the registry keys of each service Windows sees is installed. So I want to look for SQL Server service, which the key will list as the name of the instance (default being mssqlserver, named instance being mssql$nameIT). So I know the key will contain "MSSQL", but for this script to check multiple servers I don't know the full name of the key.
The only issue is that if you are looking for the Key (Default) and no value is set, then you will get a null value back even though the (Default) string value exists.
I've been looking at modifying this routine. This is my first script, so please excuse any lack of knowledge.
What I want to do once this has found the key is then to say, find a value within the key, and if its equal to 272 - then to change it to 0 - is that possible?
"THE REGISTRY KEY DOES NOT EXIST" Fix: I'd like to REALLY reiterate hitchy's comment that you must change the Get_Value method to the right one. I was banging my head until I scrolled down, read the posts and realized why it couldn't find my BINARY value. Helps to read the methods available for StdRegProv: msdn.microsoft.com/.../aa393664(v=vs.85).aspx
If you're looking to see if a key (not an item) exists, substitute strValueName = "".
This is good advice, but:
"If you run into situations where it doesn’t work, please let us know."
If you read a MULTI_SZ (into an array), the array returned is Null regardless of whether the key either doesn't exist or exists and has no value set.
Old topic, but I had an idea...
reg query or reg compare
Perhaps you could write a .bat to do the compare for you. Or you could have a script call the .bat or powershell script??
Hey I am getting the below error, do you have any idea how to resolve it?
WshShell.RegRead: Invalid root in registry key "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App paths\winzip32.exe