How can I determine the Windows version from a VB 6 app?
Asked Answered
A

7

20

I want to detect any Windows versions from 95 to Win 7.

I also would like to display if the OS is 32-bit or 64-bit.

That's it; it's that simple. :) What code could I use to do this from within a VB 6 application?

Anatole answered 29/1, 2011 at 20:24 Comment(0)
L
29

Update: For code that correctly detects Windows 8.1 and Windows 10, see this answer.

The code below still works fine for older versions of Windows, but it will report anything newer than Windows 8 as being Windows 8.

The "bitness" testing code shown at the bottom (to see if the OS is 32-bit or 64-bit still works, even on Windows 10.

The following code will return a string value indicating the current version of Windows. Basically, all it's doing is getting the system version numbers from Windows using the GetVersionEx API function, and then matching those up to the known versions of Windows.

(Note that some things are not detected perfectly. For example, a 64-bit version of Windows XP would likely be reported as Server 2003. Code to determine whether the user is running Windows Vista or Server 2008, for example, has also not been written. But you can take this and tweak it as desired.)

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

Additionally, if you don't need to target the earliest versions of Windows, you can get more information by passing the OSVERSIONINFOEX structure instead. I just wrote that code in C++, and the documentation is surprisingly easy to follow.


Determining if the host OS is 32-bit or 64-bit from a VB 6 executable is a little trickier. The reason is because VB 6 can't compile 64-bit applications. Everything you write in VB 6 will run as a 32-bit application. And 32-bit applications run on 64-bit versions of Windows in the Windows-on-Windows (WOW64) subsystem. They will always report the current version of Windows as 32-bit, because that's what they see.

We can work around this by initially assuming that the host OS is 32-bit, and attempting to prove this wrong. Here's some sample code:

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
Lone answered 30/1, 2011 at 11:26 Comment(13)
osv.OSVSize = Len(osv) gets me an error in VB2010Espress: Variable 'osv' is used before it has been assigned a value....Stonecrop
@RemusRigo: Yes, of course! This code is for VB 6, the old version last updated back in around 1998. Every version of Visual Basic since 2002 (called VB 7) has been based on the .NET Framework, and was even originally called VB.NET. They've since dropped the ".NET" part because everyone's completely forgotten about VB 6. It's not even supported anymore by Microsoft because it's nearly 15 years old. VB 6 and VB.NET are totally different, and code that works in one will not work in the other. You need to write .NET code. You're looking at questions with the wrong tag.Lone
@RemusRigo: You can't fix the error. You need to write entirely different code. The fact that both languages have "VB" in the name is about the only similarity between them. If you want to program in Visual Basic 2010, you need to buy a book on VB.NET or Visual Basic 2008/2010 so that you can learn the language. Asking how to translate VB 6 code into VB.NET code is about like asking to translate C++ or Java into VB.NET. It's possible, but it's a whole lot of work and it's not a good idea. It's also not something I'd recommend to a beginner: very fraught with error.Lone
Not to mention, there are lots of simpler ways to do this in VB.NET. You don't need nearly as much code. For example, the System.Environment namespace provides methods that encapsulate all of the functionality I show in my answer above and much more.Lone
if you don't mind can i give you my email address, so we can talk, i don't want to ask/post silly questions on forums... thanksStonecrop
@RemusRigo: Erm, well, I don't know what I can tell you in e-mail. I'm not sure who told you that any modern version of VB is going to be anything like VB 6, because it's not. 10 years ago, programmers were all upset about the transition because none of their code ported over. Now, pretty much everyone in the world has made the leap and realized that they're much better off for it. VB.NET is truly object-oriented and has a lot more built-in functionality that you get for free without having to write a single line of code. I honestly don't know what else I can suggest in an email... [continued]Lone
other than to get a book and learn VB.NET. Or, if you absolutely must write VB 6 code, switch back to the VB 6 IDE (you'll have to find it on eBay or something if you don't have an MSDN subscription). The best way is getting a book on programming VB.NET. Answers on SO, no matter how good, aren't enough to teach you a language. And I'm certainly not going to be able to do it over email. Yes, some things you already know will transfer, but not everything. It'll make learning it easier, but it doesn't make it unnecessary. But feel free to post new questions--no question is too basic here.Lone
And for Windows 8, dwVerMajor=6, dwVerMinor = 2.Hunsaker
Just going to point this out since my first couple edits were accepted, but apparently my previous edits are not being accepted. GetVersionEx is fully depreciated in Windows 10 which shows Kernel 6.2 or sometimes 6.3 and displays as Windows 8 or Windows 8.1. That means nether 6.4 or 10 will be received as the version number using GetVersionEx ever (which apparently was acceptable for my first edit even though it was wrong). Anything reporting 6.2 or 6.3 (Windows 8) from GetVersionEx is now questionable since the API depreciation and needs to use a different solution.Wrapped
@Wrapped Sorry, I just now noticed your comment here, and your edits. I was not involved in approving the original edits. GetVersionEx is not really "questionable", it is just now subject to compatibility shims that cause it to report an older version of the OS unless the application has a manifest that explicitly declares support for Windows 8 or 10. That can of course be done for a VB 6 app, but the IDE obviously doesn't include such a manifest by default. More details are available online.Lone
Honestly, I don't think it makes sense to update this answer. There is a lot of additional complexity. It really should be asked as a new question, to which I (or someone else) can post a completely different answer that takes Windows 8 and 10 into account. You see, VerifyVersionInfo is the supposed "replacement" for the "deprecated" GetVersionEx, and VerifyVersionInfo can be used in a roundabout way to determine if the current version is 8 or 8.1, but it was again broken on Windows 10. Now you get the same compatibility behavior unless you have a manifest.Lone
Hey Cody. I think it makes sense to update this answer because its the first thing Google lists when approaching anything near this subject. Your answer is perfect apart from the depreciation since the answer was created. The last edit I made was to show how you can use the depreciated GetVersionEx up until windows 8, where it then gets the version information from from the next supported answer, which is using WMI. I've tested the WMI and it works from at least Windows 7 and up.Wrapped
@brogan I finally got inspired enough to update the answer. I wrote it as a new question so that I could explain all the complicated nuances of how things work now (what I started going into in the comments here). I think that keeps the answer cleaner and the information easier to find. I've cross-linked both posts, just in case!Lone
P
4

There's also the 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

You can do something similar to the case statements provided by Cody Gray above to parse the Version value, or parse the plain text Caption value, which has listings like Microsoft(R) Windows(R) Server 2003, Standard Edition and Microsoft Windows 7 Professional.

Petey answered 29/10, 2013 at 15:28 Comment(0)
M
2

You could try using the Microsoft Sysinfo control that comes with VB6 and check for OSPlatform, OSBuild and OSVersion propertys to match with the proper OS Version #

Mcginley answered 29/1, 2011 at 21:53 Comment(0)
G
1

The accepted answer worked for my application until I tried it on Windows 10. Even after updating the code for version number details as listed here it reported the wrong Windows version. It turns out this is because:

Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases. To manifest your applications for Windows 8.1 or Windows 10, refer to Targeting your application for Windows.

So in order to get the correct Windows version to show up, it amounts to adding a section the application manifest:

   <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>

And then the GetVersionInfo API works as expected. This manifest section was new as of Windows 7, I believe.

However, a very important caveat is that you must actually have tested your application on each operating system version that you list it as being compatible with. These settings affect certain Windows functions, not only the way Windows version information is reported.

Grillparzer answered 21/4, 2016 at 18:27 Comment(1)
Nice, for more info see Cody Gray's updated link up top. Although the first answer here suits my purposes as don't care about W10 version (albeit running it) :P,Marlyn
N
1

Here is a very simple method I use to determine 32 vs. 64 bit operating system:

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

In 64-bit Windows, the OS sets the environment variable "PROGRAMFILES(X86)" but it doesn't on 32-bit systems. It hasn't failed me yet...

Naive answered 2/10, 2016 at 11:54 Comment(0)
V
0

Ah, found it! I don't personally use this class because for my needs it's overkill, but it's definitely the most thorough OpSys version example I've come across. Credit for this one goes to Kenneth Ives.

*I guess StackOverflow doesn't like enormous blocks of code, so the class (clsOperSystem.cls) is located in the KiCrypt Demo, an excellent compilation of hash and encryption algorithms.

Vocalism answered 29/1, 2011 at 21:37 Comment(0)
V
0

WORK on WINDOWS 10 VB6 - not work in debug mode - work only on runtime

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

call

Dim lpVersionInformation As RTL_OSVERSIONINFOEX
lpVersionInformation.dwOSVersionInfoSize = Len(lpVersionInformation)
RtlGetVersion(lpVersionInformation)
Vampire answered 7/7, 2017 at 15:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.