Search code examples
vbscriptwindows-installerwmi

Calling EnumKey in vbscript as custom action in an installer querying windows registry results in wbemErrNotFound


With the examples in here, I have created a vbscript which uses WMI registry object to enumerate the sub-keys on the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components". The vbscript runs fine and produces the result I need when I test it using WScript.

When I embedded the vbscript into in installer as a custom action, the EnumKey call returns error wbemErrNotFound(2). However, it could return successful result if I enumerate some other keys. Is it permission issue? I have tried running the installer in elevated privilege. How do I get it working with the installer?

For demonstrating the problem, below is a cut down version of the vbscript I am using:

Const HKEY_LOCAL_MACHINE = &H80000002
Const KEY_ENUMERATE_SUB_KEYS = &H00000008

Function CountSubKeys(nHiveRoot, sKeyPath)
    Const sComputer = "."       ' Use . for current machine

    Dim nRet
    Dim nSum

    MsgBox "EnumKey: " & sKeyPath, vbOkOnly, "CountSubKeys"
'    Set oReg = GetObject( "winmgmts:{impersonationLevel=impersonate}!//" & sComputer & "/root/default:StdRegProv" )
    Set oReg = GetObject( "winmgmts:{impersonationLevel=impersonate}!//" & sComputer & "/root/cimv2:StdRegProv" )

    Dim bGranted
    nRet = oReg.CheckAccess(nHiveRoot, sKeyPath, KEY_ENUMERATE_SUB_KEYS, bGranted)
    If (nRet = 0) Then
        If bGranted = True Then
            MsgBox "Access to key: " & sKeyPath & " is granted", vbOkOnly, "CountSubKeys"
        Else
            MsgBox "Access to key: " & sKeyPath & " is denied", vbOkOnly, "CountSubKeys"
        End If
    Else
        MsgBox "Failed to check key access: " & sKeyPath & ", nRet: " & nRet, vbOkOnly, "CountSubKeys"
    End If

    nRet = oReg.EnumKey(nHiveRoot, sKeyPath, arrSubKeys)
    If (nRet = 0) Then
        If isArray(arrSubKeys) Then
            nSum = UBound(arrSubKeys) + 1
            MsgBox "Number of sub keys: " & nSum, vbOkOnly, "CountSubKeys"
        Else
            MsgBox "EnumKey return no sub key on path" & sKeyPath, vbOkOnly, "CountSubKeys"
            nSum = 0
        End If
    Else
        MsgBox "Failed to enum key: " & sKeyPath & ", Err: " & nRet, vbOkOnly, "CountSubKeys"
        nSum = -1
    End If
    CountSubKeys = nSum
End Function

Sub TestEnumKey()
    Const sInstalledComponentKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\"

    nCount = CountSubKeys(HKEY_LOCAL_MACHINE, sInstalledComponentKey)
    MsgBox "nCount: " & nCount, vbOkOnly, "TestEnumKey"
End Sub

TestEnumKey()

The custom action uses the Sub TestEnumKey() as the entry point of the vbscrpt.


Solution

  • The error is not caused by permission of the registry key. It is due to the accessing of 64-bits registry on a 32-bits scripting host.

    When I tested the vbscript using WScript, it is by default using the 64-bits scripting host and accessing the 64-bits registry by default and successfully enumerate the subkeys.

    My installer is an 32-bits msi and therefore its custom action invokes 32-bits scripting host, which accesses the 32-bits registry by default, and of course cannot find the 64-bit registry key.