【问题标题】:How can I determine the Windows version from a VB 6 app?如何从 VB 6 应用程序确定 Windows 版本?
【发布时间】:2011-06-17 20:59:39
【问题描述】:

我想检测从 95 到 Win 7 的任何 Windows 版本。

我还想显示操作系统是 32 位还是 64 位。

就是这样;就这么简单。 :) 我可以在 VB 6 应用程序中使用什么代码来执行此操作?

【问题讨论】:

    标签: windows vb6 32bit-64bit windowsversion


    【解决方案1】:

    更新:有关正确检测 Windows 8.1 和 Windows 10 的代码,请参阅this answer

    下面的代码仍然适用于旧版本的 Windows,但它会将比 Windows 8 更新的任何东西报告为 Windows 8。

    底部显示的“位”测试代码(查看操作系统是 32 位还是 64 位仍然有效,即使在 Windows 10 上也是如此。

    以下代码将返回一个字符串值,指示当前的 Windows 版本。基本上,它所做的只是使用GetVersionEx API function 从 Windows 获取系统版本号,然后将它们与已知的 Windows 版本进行匹配。

    (请注意,有些东西没有被完美检测到。例如,Windows XP 的 64 位版本可能会报告为 Server 2003。例如,用于确定用户运行的是 Windows Vista 还是 Server 2008 的代码有也没有写。但你可以根据需要调整它。)

    Option Explicit
    
    Private Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" _
        (lpVersionInformation As OSVERSIONINFO) As Long
    
    Private Type OSVERSIONINFO
      OSVSize         As Long
      dwVerMajor      As Long
      dwVerMinor      As Long
      dwBuildNumber   As Long
      PlatformID      As Long
      szCSDVersion    As String * 128
    End Type
    
    Private Const VER_PLATFORM_WIN32s = 0
    Private Const VER_PLATFORM_WIN32_WINDOWS = 1
    Private Const VER_PLATFORM_WIN32_NT = 2
    
    ' Returns the version of Windows that the user is running
    Public Function GetWindowsVersion() As String
        Dim osv As OSVERSIONINFO
        osv.OSVSize = Len(osv)
    
        If GetVersionEx(osv) = 1 Then
            Select Case osv.PlatformID
                Case VER_PLATFORM_WIN32s
                    GetWindowsVersion = "Win32s on Windows 3.1"
                Case VER_PLATFORM_WIN32_NT
                    GetWindowsVersion = "Windows NT"
                    
                    Select Case osv.dwVerMajor
                        Case 3
                            GetWindowsVersion = "Windows NT 3.5"
                        Case 4
                            GetWindowsVersion = "Windows NT 4.0"
                        Case 5
                            Select Case osv.dwVerMinor
                                Case 0
                                    GetWindowsVersion = "Windows 2000"
                                Case 1
                                    GetWindowsVersion = "Windows XP"
                                Case 2
                                    GetWindowsVersion = "Windows Server 2003"
                            End Select
                        Case 6
                            Select Case osv.dwVerMinor
                                Case 0
                                    GetWindowsVersion = "Windows Vista/Server 2008"
                                Case 1
                                    GetWindowsVersion = "Windows 7/Server 2008 R2"
                                Case 2
                                    GetWindowsVersion = "Windows 8/Server 2012"
                                Case 3
                                    GetWindowsVersion = "Windows 8.1/Server 2012 R2"
                            End Select
                    End Select
            
                Case VER_PLATFORM_WIN32_WINDOWS:
                    Select Case osv.dwVerMinor
                        Case 0
                            GetWindowsVersion = "Windows 95"
                        Case 90
                            GetWindowsVersion = "Windows Me"
                        Case Else
                            GetWindowsVersion = "Windows 98"
                    End Select
            End Select
        Else
            GetWindowsVersion = "Unable to identify your version of Windows."
        End If
    End Function
    

    此外,如果您不需要针对最早版本的 Windows,则可以通过传递 OSVERSIONINFOEX structure 来获取更多信息。我刚刚用 C++ 编写了该代码,而且文档非常容易理解。


    从 VB 6 可执行文件确定主机操作系统是 32 位还是 64 位有点棘手。原因是因为 VB 6 不能编译 64 位应用程序。您在 VB 6 中编写的所有内容都将作为 32 位应用程序运行。 32 位应用程序在 Windows-on-Windows (WOW64) 子系统中的 64 位版本的 Windows 上运行。他们将始终将当前版本的 Windows 报告为 32 位,因为这就是他们所看到的。

    我们可以通过最初假设主机操作系统是 32 位并尝试证明这是错误的来解决这个问题。下面是一些示例代码:

    Private Declare Function GetProcAddress Lib "kernel32" _
        (ByVal hModule As Long, ByVal lpProcName As String) As Long
        
    Private Declare Function GetModuleHandle Lib "kernel32" _
        Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
        
    Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
    
    Private Declare Function IsWow64Process Lib "kernel32" _
        (ByVal hProc As Long, ByRef bWow64Process As Boolean) As Long
    
    Public Function IsHost64Bit() As Boolean
        Dim handle As Long
        Dim is64Bit As Boolean
    
        ' Assume initially that this is not a WOW64 process
        is64Bit = False
    
        ' Then try to prove that wrong by attempting to load the
        ' IsWow64Process function dynamically
        handle = GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process")
    
        ' The function exists, so call it
        If handle <> 0 Then
            IsWow64Process GetCurrentProcess(), is64Bit
        End If
    
        ' Return the value
        IsHost64Bit = is64Bit
    End Function
    

    【讨论】:

    • osv.OSVSize = Len(osv) 在 VB2010Espress 中给我一个错误:变量 'osv' 在被赋值之前被使用......
    • @RemusRigo:是的,当然!此代码适用于 VB 6,旧版本最后一次更新是在 1998 年左右。每个版本的自 2002 年以来的 Visual Basic(称为 VB 7)一直基于 .NET Framework,甚至最初称为 VB.NET。他们已经放弃了“.NET”部分,因为每个人都完全忘记了 VB 6。微软甚至不再支持它,因为它已经快 15 年了。 VB 6 和 VB.NET完全不同,在一个中工作的代码在另一个中不起作用。您需要编写 .NET 代码。您正在查看带有错误标签的问题。
    • @RemusRigo:你无法修复错误。您需要编写完全不同的代码。两种语言的名称中都有“VB”这一事实是它们之间唯一的相似之处。如果你想用 Visual Basic 2010 编程,你需要买一本关于 VB.NET 或 Visual Basic 2008/2010 的书,这样你才能学习这门语言。询问如何将 VB 6 代码翻译成 VB.NET 代码就像要求将 C++ 或 Java 翻译成 VB.NET。这是可能的,但工作量很大,而且不是一个好主意。这也不是我向初学者推荐的东西:非常错误。
    • 除了买书和学习 VB.NET。或者,如果您绝对必须编写 VB 6 代码,请切换回 VB 6 IDE(如果您没有订阅 MSDN,则必须在 eBay 或其他地方找到它)。最好的方法是获得一本关于编程 VB.NET 的书。 SO上的答案,无论多么好,都不足以教你一门语言。我当然不能通过电子邮件做到这一点。是的,你已经知道的一些事情会转移,但不是所有的事情。它会让学习变得更容易,但不会让它变得不必要。但请随时发布新问题——这里没有任何问题太基本。
    • 对于 Windows 8,dwVerMajor=6,dwVerMinor = 2。
    【解决方案2】:

    还有WMI Tasks for Operating Systems

    strComputer = "."
    Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
    For Each objOperatingSystem in colOperatingSystems
        Wscript.Echo objOperatingSystem.Caption & "  " & objOperatingSystem.Version
    Next
    

    您可以执行与上面 Cody Gray 提供的案例语句类似的操作来解析 Version 值,或解析纯文本 Caption 值,其中包含 Microsoft(R) Windows(R) Server 2003, Standard EditionMicrosoft Windows 7 Professional 等列表。

    【讨论】:

      【解决方案3】:

      您可以尝试使用 VB6 附带的 Microsoft Sysinfo control 并检查 OSPlatform、OSBuild 和 OSVersion 属性以匹配正确的 OS Version #

      【讨论】:

        【解决方案4】:

        在我在 Windows 10 上尝试之前,接受的答案对我的应用程序有效。即使在更新了版本号详细信息的代码as listed here 之后,它也报告了错误的 Windows 版本。原来这是因为:

        未针对 Windows 8.1 或 Windows 10 显示的应用程序将返回 Windows 8 操作系统版本值 (6.2)。一旦针对给定的操作系统版本显示应用程序,GetVersionEx 将始终返回应用程序在未来版本中显示的版本。要为 Windows 8.1 或 Windows 10 显示您的应用程序,请参阅 Targeting your application for Windows

        因此,为了显示正确的 Windows 版本,这相当于在应用程序清单中添加一个部分:

           <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
               <application> 
                   <!-- Windows 10 --> 
                   <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
                   <!-- Windows 8.1 -->
                   <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
                   <!-- Windows Vista -->
                   <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
                   <!-- Windows 7 -->
                   <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
                   <!-- Windows 8 -->
                   <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
               </application> 
           </compatibility>
        

        然后 GetVersionInfo API 按预期工作。我相信这个清单部分是 Windows 7 的新内容。

        但是,一个非常重要的警告是,您必须在您列出的兼容的每个操作系统版本上实际测试过您的应用程序。这些设置会影响某些 Windows 功能,而不仅仅是报告 Windows 版本信息的方式。

        【讨论】:

        • 很好,有关更多信息,请参阅 Cody Gray 的更新链接。虽然这里的第一个答案适合我的目的,因为不关心 W10 版本(尽管正在运行它):P,
        【解决方案5】:

        这是我用来确定 32 位和 64 位操作系统的一个非常简单的方法:

        OSBits = IIf(Len(Environ$("PROGRAMFILES(X86)")) > 0, 64, 32)
        

        在 64 位 Windows 中,操作系统设置环境变量“PROGRAMFILES(X86)”,但在 32 位系统上不设置。它还没有让我失望......

        【讨论】:

          【解决方案6】:

          啊,找到了!我个人不使用这个类,因为对于我的需要它是矫枉过正的,但它绝对是我遇到的最彻底的 OpSys 版本示例。这要归功于肯尼斯·艾夫斯。

          *我猜 StackOverflow 不喜欢庞大的代码块,所以类 (clsOperSystem.cls) 位于 KiCrypt Demo,这是哈希和加密算法的优秀汇编。

          【讨论】:

            【解决方案7】:

            在 WINDOWS 10 上工作 VB6 - 不能在调试模式下工作 - 只能在运行时工作

            Private Declare Function RtlGetVersion Lib "ntdll" (ByRef lpVersionInformation As RTL_OSVERSIONINFOEX) As Long
            
            Private Type RTL_OSVERSIONINFOEX
                    dwOSVersionInfoSize As Long
                    dwMajorVersion As Long
                    dwMinorVersion As Long
                    dwBuildNumber As Long
                    dwPlatformId As Long
                    szCSDVersion As String * 128
            End Type
            

            打电话

            Dim lpVersionInformation As RTL_OSVERSIONINFOEX
            lpVersionInformation.dwOSVersionInfoSize = Len(lpVersionInformation)
            RtlGetVersion(lpVersionInformation)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-11-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-01-10
              • 2022-10-12
              相关资源
              最近更新 更多