How do I read 64-bit Registry values from VBScript running as a an msi post-installation task?

29,306

Solution 1

Not sure about launching the 64-bit script host version, but you should be able to access the 64-bit registry from the 32-bit script host using the WMI StdRegProv class, like this:

Const HKEY_LOCAL_MACHINE = &H80000002
sPath = ReadRegStr (HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\ASP.NET\2.0.50727.0", "Path", 64)
WScript.Echo sPath

' Reads a REG_SZ value from the local computer's registry using WMI.
' Parameters:
'   RootKey - The registry hive (see http://msdn.microsoft.com/en-us/library/aa390788(VS.85).aspx for a list of possible values).
'   Key - The key that contains the desired value.
'   Value - The value that you want to get.
'   RegType - The registry bitness: 32 or 64.
'
Function ReadRegStr (RootKey, Key, Value, RegType)
    Dim oCtx, oLocator, oReg, oInParams, oOutParams

    Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
    oCtx.Add "__ProviderArchitecture", RegType

    Set oLocator = CreateObject("Wbemscripting.SWbemLocator")
    Set oReg = oLocator.ConnectServer("", "root\default", "", "", , , , oCtx).Get("StdRegProv")

    Set oInParams = oReg.Methods_("GetStringValue").InParameters
    oInParams.hDefKey = RootKey
    oInParams.sSubKeyName = Key
    oInParams.sValueName = Value

    Set oOutParams = oReg.ExecMethod_("GetStringValue", oInParams, , oCtx)

    ReadRegStr = oOutParams.sValue
End Function

NB: I'm under a 32-bit OS right now, so can't verify that this example works. Beware of bugs :-)

See also the Requesting WMI Data on a 64-bit Platform MSDN article for more info on the subject.

Solution 2

Using Microsoft's documented approach, Helen's answer is absolutely correct.

However according to my own tests it turns out that it is enough to specify the __ProviderArchitecture context flag only at the time the connection to the StdRegProv provider is established.
This makes things much simpler as only setting up the provider needs to be encapsulated in a separate function, otherwise one can use the regular API.

set reg64 = MakeRegLocator(64)
reg64.GetStringValue , "SOFTWARE\Microsoft\ASP.NET\2.0.50727.0", "Path", path

WScript.Echo path

' Establish a connection to the local 32 or 64 bit registry hive as requested.
' Parameters:
'   RegType - The registry bitness: 32 or 64.
function MakeRegLocator(bitness)
    set ctx = CreateObject("WbemScripting.SWbemNamedValueSet")
    ctx.Add "__ProviderArchitecture", bitness

    set locator = CreateObject("Wbemscripting.SWbemLocator")
    set services = locator.ConnectServer("", "root\default", "", "", , , , ctx)
    set reg = services.Get("StdRegProv")

    set MakeRegLocator = reg
end function
Share:
29,306
Joergen Bech
Author by

Joergen Bech

Updated on April 08, 2020

Comments

  • Joergen Bech
    Joergen Bech about 4 years

    I need to read the location of the Temporary ASP.NET Files folder from VBScript as part of a post-installation task in an installer created using a Visual Studio 2008 deployment project.

    I thought I would do something like this:

    Set oShell = CreateObject("Wscript.Shell")
    strPath = oShell.RegRead("HKLM\SOFTWARE\Microsoft\ASP.NET\2.0.50727.0\Path")
    

    and then concatenate strPath with "\Temporary ASP.NET Files" and be done with it.

    On an x64 system, however, I am getting the value from the WOW6432Node (HKLM\SOFTWARE\Wow6432Node\Microsoft\ASP.NET\2.0.50727.0), which gives me the 32-bit framework path (C:\Windows\Microsoft.NET\Framework\v2.0.50727), but on an x64 system, I actually want the 64-bit path, i.e. C:\Windows\Microsoft.NET\Framework64\v2.0.50727.

    I understand that this happens because the .vbs file is run using the 32-bit script host due to the parent process (the installer) being 32-bit itself.

    How can I run the script using the 64-bit script host - or - how can I read the 64-bit values even if the script is run using the 32-bit script host?

  • Danielle Paquette-Harvey
    Danielle Paquette-Harvey over 10 years
    How do you do that, but to verify only a key, not a value?? (Ex: see if "SOFTWARE\Microsoft\ASP.NET\2.0.50727.0" exists but not the "Path" value
  • Helen
    Helen over 10 years
    @DaniellePaquette-Harvey: You need to call EnumKey instead of GetStringValue (with appropriate parameters) and check if oOutParams.ReturnValue is 0. Also, see answers in this question: Check if registry key exists.
  • Fowl
    Fowl over 6 years
    AutoIt Script is not VBScript, the functions aren't the same
  • klaus triendl
    klaus triendl over 5 years
    @DaniellePaquette-Harvey Alternatively you can query the standard value oReg.GetStringValue , "SOFTWARE\Microsoft\ASP.NET\2.0.50727.0", , stdv and then check IsNull(stdv). Technique inspired from The Scripting Guys