How do I check if wscript/cscript runs on x64 host

2020-03-23 11:49发布

问题:

I'm running a VBScript that may run under x64 Windows. I need to read a registry key from the 32-bit part of the registry. For that I use path HKLM\Software\Wow6432Node\xyz instead of HKLM\Software\xyz. How can I check if the script is executed under x64?

回答1:

I'm not sure you need to check if the script is executing under x64.

Try to read from HKLM\Software\Wow6432Node\xyz, if that fails, try to read from HKLM\Software\xyz, if that fails, your registry key doesn't exist, take whatever action is appropriate.

Of course, if your design is more complicated (for example, you write a value into that registry key if it doesn't exist) then that suggestion won't work.

Here is a VBScript for examining the operating system. You'll probably also need explanation of the Properties available from the Win32_OperatingSystem Class

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")        

Set colOperatingSystems = objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")

For Each objOperatingSystem in colOperatingSystems
    msg = objOperatingSystem.Caption & " " & _
            objOperatingSystem.Version & " " & _
                objOperatingSystem.OSArchitecture
    msgbox msg
Next

Note that for Windows XP and 2003, OSArchitecture is not available, in which case you will probably have to examine either the Caption or Version to determine whether your OS is 64-bit.

You could also use something like this depending on the level of complexity you require.



回答2:

Even on 64-bit version of Windows you script can execute in 32-bit mode.

You can use following code to determine real bit mode, you script running on:

option explicit

function Determine64BitMode
    dim Shell, Is64BitOs
    set Shell = CreateObject("WScript.Shell")
    on error resume next
    Shell.RegRead "HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir (x86)"
    Is64BitOs = Err.Number = 0
    on error goto 0
    if Is64BitOs then
        Determine64BitMode = InStr(Shell.RegRead("HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir"), "(x86)") = 0
    else
        Determine64BitMode = false
    end if
end function

dim ExecutingIn64BitMode
ExecutingIn64BitMode = Determine64BitMode
if ExecutingIn64BitMode then
    MsgBox "64 bit"
else
    MsgBox "32 bit"
end if


回答3:

You didn't mention what API you use to read from the registry. For example, if you use the WMI StdRegProv class, you can use the __ProviderArchitecture flag to request access to the 32-bit registry hive regardless of whether the script is run under 32-bit or 64-bit Windows Script Host. This technique is described in the Requesting WMI Data on a 64-bit Platform article in MSDN.

Here's an example of reading from the 32-bit registry:

strComputer = "."
Const HKLM = &h80000002

''# Specify the required registry bitness
Set oCtx = CreateObject("WbemScripting.SWbemNamedValueSet")
oCtx.Add "__ProviderArchitecture", 32
oCtx.Add "__RequiredArchitecture", True

''# Load the 32-bit registry provider
Set oLocator = CreateObject("WbemScripting.SWbemLocator")
Set oWMI = oLocator.ConnectServer(strComputer, "root\default",,,,,, oCtx)
Set oReg = oWMI.Get("StdRegProv") 

''# Specify input parameters for the GetStringValue method call
Set oInParams = oReg.Methods_("GetStringValue").InParameters
oInParams.hDefKey     = HKLM
oInParams.sSubKeyName = "Software\xyz"
oInParams.sValueName  = "foobar"

''# Read a string value from the registry
Set oOutParams = oReg.ExecMethod_("GetStringValue", oInParams,, oCtx)
WScript.Echo oOutParams.sValue

Note also, that in this case the 32-bit key names should be specified in a usual way as HKLM\Software\xyz instead of HKLM\Software\Wow6432Node\xyz.



回答4:

Here is a solution based on the Microsoft knowledgebase article How To Check If Computer Is Running A 32 Bit or 64 Bit Operating System:

Function Is64BitOS()
    Is64BitOS = Not(Is32BitOS())
End Function

Function Is32BitOS()
    Const sRegKey = "HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0"
    Const sIdentifierValue = "Identifier"
    Const sPlatformIDValue = "Platform ID"

    Dim oSh : Set oSh = CreateObject("WScript.Shell")
    Dim sIdentifier, nPlatformID

    sIdentifier = oSh.RegRead(sRegKey & "\" & sIdentifierValue)
    nPlatformID = oSh.RegRead(sRegKey & "\" & sPlatformIDValue)

    Set oSh = Nothing

    If InStr(sIdentifier, "x86") > 0 And nPlatformID = 32 Then
        Is32BitOS = True
    Else
        Is32BitOS = False
    End if
End Function

ALTERNATIVE SOLUTION

An alternative and more concise solution that makes use of WMI can be found here.



回答5:

A very simple solution is to check whether (virtual) folder C:\Windows\sysnative exist. This folder exists only in 32-Bit processes, see File System Redirector

Set fso = CreateObject("Scripting.FileSystemObject")
Set wshShell = CreateObject( "WScript.Shell" )

If fso.FolderExists(wshShell.ExpandEnvironmentStrings("%windir%") & "\sysnative" ) Then
    WScript.Echo "You are running in 32-Bit Mode"
Else
    WScript.Echo "You are running in 64-Bit Mode"
End if

Note, works only on Windows Server 2003 and Windows XP or higher.



回答6:

This shows both the system and process architectures:

Option Explicit
Dim WshShell, WshEnv
Set WshShell = WScript.CreateObject("WScript.Shell")
Set WshEnv = WshShell.Environment("System")
MsgBox "System: " & WshEnv("PROCESSOR_ARCHITECTURE")
Set WshEnv = WshShell.Environment("Process")
MsgBox "Process: " & WshEnv("PROCESSOR_ARCHITECTURE")

Just check the one you need for <> "x86".