Tag Archives: WMI

Two ways to check if a Registry Key exists using VBScript

The first one is using the method RegRead from WScript.Shell.

If the given key is not found, it will rise an error, so we need to use an On Error Resume Next (which I don’t really like).

We would need to pass to the function a string like HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\ (note the trailing \) if we are looking for a Registry Key (those that look like a folder). If we want to check if a value inside a key exists, we would remove the trailing \, like HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\CurrentLevel.

Function RegKeyExists(Key)
  Dim oShell, entry
  On Error Resume Next
  Set oShell = CreateObject("WScript.Shell")
  entry = oShell.RegRead(Key)
  If Err.Number <> 0 Then
    RegKeyExists = False
    RegKeyExists = True
  End If
End Function

The second method uses WMI.

In this case, we would need to pass the Key Hive (Current User, Local Machine, etc) in the form of hex numbers (I declared them as constants). The KeyPath would be something like SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings.

Const HKCR = &H80000000 'HKEY_CLASSES_ROOT
Const HKCU = &H80000001 'HKEY_CURRENT_USER
Const HKUS = &H80000003 'HKEY_USERS
Function KeyExists(Key, KeyPath)
  Dim oReg: Set oReg = GetObject("winmgmts:!root/default:StdRegProv")
  If oReg.EnumKey(Key, KeyPath, arrSubKeys) = 0 Then
    KeyExists = True
    KeyExists = False

The difference with this function is that will only check for Registry Keys and not for values.

Fixing WMI Service (root\cimv2 namespace missing)

I was working on a VBScript code that uses the Windows Management Instrumentation (WMI) to query the running processes on the local machine, something like this:

strComputer = "."
strProcess2Kill = "something.exe"
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcess = objWMIService.ExecQuery("Select * from Win32_Process Where Name = " & strProcess2Kill)
For Each objProcess In colProcess
	'Now we will each one of the running processes "something.exe"

This code works in, at least, Win2k, WinXP, WinVista and Win7 (not sure if works on WinNt 4). The problem I had (as you can see here) was that the box where it should have been deployed (Win2k) showed an 0x8004100E error (Namespace specified cannot be found) on the 4th line of the code.

When I ran the following script to query all the namespaces on root:

strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & "\root")
Set colNameSpaces = objSwbemServices.InstancesOf("__NAMESPACE")
For Each objNameSpace In colNameSpaces
 Wscript.Echo objNameSpace.Name

I got this:


As you can see, the CIMV2 namespace was not present and it should have been. So, something was wrong with the WMI installation on that box.

Then, I ran a very nice tool called wmidiag.vbs (pointed by user Uros Calakovic on my StackOverflow question) to diagnose several problems with WMI. Unfortunately, the tool gave me the same error and no proposed solution. He also mention a couple of interesting screencasts that more than one may find useful.

At the end, Google gave me the final answer once again. Reinstalling the WMI into the Windows Registry and rebuilding the WMI Repository did the trick (I did both, but maybe only the Repository rebuilding helped me this time).

In any case, to rebuild the WMI Repository, these are the only required steps:

  • Stop the WMI service (net stop winmgmt)
  • Go to %windows%/system32/wbem (in my win2k, winnt, on XP would be windows)
  • Rename or remove the repository directory
  • Start the WMI service again (net start winmgmt)

And for reinstalling WMI, you should run these commands on a console:

winmgmt /clearadap
winmgmt /kill
winmgmt /unregserver
winmgmt /regserver
winmgmt /resyncperf