如何使用VBScript确定我运行的是32位还是64位的Windows操作系统?

12

我该如何在VBScript中检测Windows操作系统的位数(32位还是64位)?

我尝试了这种方法,但它并不起作用;我猜(x86)可能会导致一些问题,在检查文件夹时...

是否有其他替代方案?

progFiles="c:\program files" & "(" & "x86" & ")"

set fileSys=CreateObject("Scripting.FileSystemObject")

If fileSys.FolderExists(progFiles) Then    
   WScript.Echo "Folder Exists"    
End If

不,我认为他想知道自己是否在运行32位或64位操作系统。因此,这是https://dev59.com/UnVC5IYBdhLWcg3ww0Hr的副本。 - Treb
可能是重复的问题:确定64位还是32位Windows - Treb
@Treb:没有VBScript的答案。二话不说,这可能是https://dev59.com/0UbRa4cB1Zd3GeqP1pbe的重复。 - Helen
10个回答

23

最近在工作中遇到了同样的问题。偶然发现了这个天才的VBScript,觉得它太好了不分享一下可惜了。

Bits = GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'").AddressWidth

来源: http://csi-windows.com/toolkit/csi-getosbits


4
+1.49 - 很好的解决方案 - 但是 - 遗憾的是 - 它运行在 WMI 时间上(以茶杯计量)。 - Ekkehard.Horner

16

您可以查询PROCESSOR_ARCHITECTURE。如此处所述,您需要添加一些额外的检查,因为对于任何32位进程,PROCESSOR_ARCHITECTURE的值都将是x86,即使它在64位操作系统上运行。在这种情况下,变量PROCESSOR_ARCHITEW6432将包含操作系统的位数。更多细节请参见MSDN

Dim WshShell
Dim WshProcEnv
Dim system_architecture
Dim process_architecture

Set WshShell =  CreateObject("WScript.Shell")
Set WshProcEnv = WshShell.Environment("Process")

process_architecture= WshProcEnv("PROCESSOR_ARCHITECTURE") 

If process_architecture = "x86" Then    
    system_architecture= WshProcEnv("PROCESSOR_ARCHITEW6432")

    If system_architecture = ""  Then    
        system_architecture = "x86"
    End if    
Else    
    system_architecture = process_architecture    
End If

WScript.Echo "Running as a " & process_architecture & " process on a " _ 
    & system_architecture & " system."

我必须在这里添加一个非常重要的注释...如果您运行32位CMD shell并在该shell内运行64位wscript/cscript可执行文件,则代码中的此检查将正确返回“x86”。但是,如果您要在代码中加载COM DLL或类似内容,则主机会将它们加载为64位DLL。在我手动测试命令并且它可以工作之前,我花了四个小时来解决这个问题,我知道有些地方不对劲。 - henry700

6

以下是基于@Bruno非常简洁答案的VBScript函数:

Function Is32BitOS()
    If GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'").AddressWidth _
       = 32 Then
        Is32BitOS = True
    Else
        Is32BitOS = False
    End If
End Function

Function Is64BitOS()
    If GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'").AddressWidth _
       = 64 Then
        Is64BitOS = True
    Else
        Is64BitOS = False
    End If
End Function

更新: 根据 @Ekkehard.Horner 的建议,下面这两个函数可以使用单行语法更简洁地编写:

Function Is32BitOS() : Is32BitOS = (GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'").AddressWidth = 32) : End Function

Function Is64BitOS() : Is64BitOS = (GetObject("winmgmts:root\cimv2:Win32_Processor='cpu0'").AddressWidth = 64) : End Function

请注意,括号不是必需的,但我认为它们有助于理解运算符优先级。另外,请注意,在修订后的实现中使用的单行语法避免了使用If/Then结构!

更新2:根据@Ekkehard.Horner的反馈,一些人可能会发现这些进一步修改后的实现既简洁又易读:

Function Is32BitOS()
    Const Path = "winmgmts:root\cimv2:Win32_Processor='cpu0'"
    Is32BitOS = (GetObject(Path).AddressWidth = 32)
End Function

Function Is64BitOS()
    Const Path = "winmgmts:root\cimv2:Win32_Processor='cpu0'"
    Is64BitOS = (GetObject(Path).AddressWidth = 64)
End Function

1
有按代码行数或工时计费的人会喜欢这个;其他人会把“Function F():If条件 Then F = True Else F = False:End Function”视为臃肿。 - Ekkehard.Horner
精简版将是:“Function F() : F = Condition : End Function” - 没有三元运算符,不用考虑赋值是否交换,而且少了4行。 - Ekkehard.Horner
一个条件表达式(例如“GetObject(...)。AdressWidth = 64”)评估为布尔值,可以直接分配给函数名称(VBScript返回函数的方式)而无需进一步操作。 - Ekkehard.Horner
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/21484/discussion-between-ekkehard-horner-and-davidrr - Ekkehard.Horner
1
如果您使用3行代码,可以将条件表达式的结果直接赋值给函数名,这样就可以得到精简版本(如果您使用3行代码,也可以得到同样精简的版本;关键是将条件表达式的结果直接赋值给函数名)。 - Ekkehard.Horner

5

使用环境变量可以加快WMIC查询速度:

Function GetOsBits()
   Set shell = CreateObject("WScript.Shell")
   If shell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%") = "AMD64" Then
      GetOsBits = 64
   Else
      GetOsBits = 32
   End If
End Function

4

判断CPU是32位还是64位很容易,但问题是如何确定操作系统是32位还是64位。当64位Windows正在运行时,ProgramW6432环境变量被定义。

CreateObject("WScript.Shell").Environment("PROCESS")("ProgramW6432") = ""

这将对32位操作系统返回true,对64位操作系统返回false,并适用于包括非常老的Windows版本在内的所有版本。


如果你单独运行vbs,它默认会使用32位脚本,所以你必须使用C:\Windows\Syswow64\cscript来运行它,然后它会返回64位。 - SeanClt
你提出了一个很好的观点。老实说,我使用过这种技术,并且在Windows 2000、XP 32位、Windows 7、8和10上运行良好,但我没有在所有操作系统上进行测试。因此...这是一个简单的解决方案,可能无法在像Server 2003这样的所有Windows版本上工作。 - Regis Desrosiers
我找到了一个简单的解决方案,只需要查看C:\windows\syswow64\cacript是否存在,如果不存在就是32位。 - SeanClt
1
@seanClt:%windir%\SysWow64\CScript 存在... 除非你在运行一个剥离了 WoW64 系统的 x64 Windows 版本,例如 Windows PE、移除了 WoW64-Support 的 Server Core 等。 - AntoineL

3

补充Bruno的答案:您可能需要检查操作系统而不是处理器本身,因为您可以在较新的CPU上安装较旧的操作系统:

strOSArch = GetObject("winmgmts:root\cimv2:Win32_OperatingSystem=@").OSArchitecture

返回字符串“32位”或“64位”。

附录补充:.OSArchitecture 在 XP 上不存在。 - amonroejj
它可以返回“64位”,也可能是“64位”,这取决于本地化设置。 - FCA69

2

您还可以检查文件夹C:\Windows\sysnative是否存在。这个文件夹(或更好的别名)只存在于32位进程中,请参见文件系统重定向器

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

注意:该脚本显示当前进程是否以32位或64位模式运行,而不显示您的Windows架构。

sysnative在未更新的64位XP/2003中不存在。 - Anders
XP/2003有多少年了?20年了吗? - Wernfried Domscheit

0

使用环境。在XP中测试过,但是我找不到32位CPU来测试...

   function getbitsos()
      with WScript.CreateObject("WScript.Shell").environment("PROCESS")
        if .item("PROCESSOR_ARCHITECTURE") ="X86" and .item("PROCESSOR_ARCHITEW6432") =vbnullstring Then
          getbitsos=array(32,32,32)
        elseif .item("PROGRAMFILES(x86)")=vbnullstring Then 
          getbitsos=array(64,32,32)
        elseif .item("PROGRAMFILES(x86)")=.item("PROGRAMFILES") Then
          getbitsos=array(64,64,32)
        Else
          getbitsos=array(64,64,64)
        end if   
      end with
    end function
    
    a=getbitsos()
    wscript.echo "Processor " &a(0) & vbcrlf & "OS "  & a(1) &vbcrlf& "Process " & a(2)& vbcrlf 

0
' performance should be good enough
' Example usage for console:
' CSript //NoLogo *ScriptName*.vbs
' If ErrorLevel 1 Echo.Win32
' VBScript:
On Error Resume Next
Const TargetWidth = 32
Set WMI = GetObject("winMgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set Query = WMI.ExecQuery("SELECT AddressWidth FROM Win32_Processor")
For Each Item in Query
  If Item.AddressWidth = TargetWidth Then
    WScript.Quit 1
  End If
Next
WScript.Quit 0

虽然这段代码片段可能是解决方案,但包括解释真的有助于提高您的帖子质量。请记住,您正在回答未来读者的问题,而这些人可能不知道您的代码建议原因。 - Neo Anderson

0
这是在微软博客中提出的相同解决方案https://learn.microsoft.com/en-us/archive/blogs/david.wang/howto-detect-process-bitness
在XP 32位和Win7 64位上进行了测试(使用32位和64位CMD)。
Set objShell = CreateObject("WScript.Shell")
os_bit = 64
arch = objShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITECTURE%")
archW6432 = objShell.ExpandEnvironmentStrings("%PROCESSOR_ARCHITEW6432%")
If LCase(arch) = "x86" Then
    If archW6432 = "" Or LCase(archW6432) = "%processor_architew6432%" Then
        os_bit = 32
    End If
End If

WScript.Echo "Operating System Bit: " & os_bit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接