如何从 VB 6 应用程序确定 Windows 版本?

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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 版本示例。这要归功于肯尼斯·艾夫斯。

*我猜 *** 不喜欢庞大的代码块,所以类 (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)

【讨论】:

以上是关于如何从 VB 6 应用程序确定 Windows 版本?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 10 中从命令行构建 Visual Studio 2015 vb 解决方案

金蝶提示: 激活控件'VB.UserControl'失败.这个控件可能与您的应用程序不兼容.确定您使用的这个版.

Windows7家庭版升级为旗舰版

IBM Worklight - 如何从 Mac OS 的 6.2 切换回 6.1 版? [关闭]

《c# 从入门经典》 (第6版) - c# 简介

如何使用 VB.net 获取 Windows 控制台应用程序的文本?