-
Jun 23rd, 2017, 02:12 AM
#1
Thread Starter
Lively Member
Calling IsWindows10OrGreater from VB6 in Windows 10
Generally I use RtlGetVersion to check whether my VB6 app is running in Windows 10. But this time I wanted to know whether I can use IsWindows10OrGreater for this purpose and test this WinAPI function in various environments. Sadly enough, but I could not call it from VB6. My declarations like this
Code:
Private Declare Function IsWindows10OrGreater Lib "Kernel32" () As Boolean
simply gave me the run-time error 453 "Can't find DLL entry point". I tried it in the VB6 IDE and in the compiled exe - nothing helped.
Is it possible to call IsWindows10OrGreater from a VB6 app? Do we need to target our app for Win10 or do any other thing for that?
-
Jun 23rd, 2017, 07:42 AM
#2
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
IsWindows10OrGreater is an inline function, that calls other APIs in kernel32. It doesn't actually exist in the dll in a callable form.
I think someone posted a translated version though- lemme try and fine one.
MVersionHelpers.bas
Code:
' MVersionHelpers.bas - VB translation of VersionHelpers.h
Option Explicit
Private Const WIN32_WINNT_NT4 As Integer = &H400
Private Const WIN32_WINNT_WIN2K As Integer = &H500
Private Const WIN32_WINNT_WINXP As Integer = &H501
Private Const WIN32_WINNT_WS03 As Integer = &H502
Private Const WIN32_WINNT_WIN6 As Integer = &H600
Private Const WIN32_WINNT_VISTA As Integer = &H600
Private Const WIN32_WINNT_WS08 As Integer = &H600
Private Const WIN32_WINNT_LONGHORN As Integer = &H600
Private Const WIN32_WINNT_WIN7 As Integer = &H601
Private Const WIN32_WINNT_WIN8 As Integer = &H602
Private Const WIN32_WINNT_WINBLUE As Integer = &H603 ' Windows 8.1
Private Const WIN32_WINNT_WIN10 As Integer = &HA00
Private Const WIN32_WINNT_WIN10AU As Integer = &HA01 ' Anniversary Update
Private Const WIN32_WINNT_WIN10CU As Integer = &HA02 ' Creators Update
Private Type TOSVERSIONINFOEXW ' same as RTL_OSVERSIONINFOEXW
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion(128 * 2 - 1) As Byte
wServicePackMajor As Integer
wServicePackMinor As Integer
wSuiteMask As Integer
wProductType As Byte ' MS likes messing up type prefixes.
wReserved As Byte ' These last 2 are BYTE, not WORD (w). see winnt.h
End Type
Private Declare Function RtlGetVersion Lib "ntdll" (ByRef lpVersionInformation As Any) As Long
Private Declare Function VerSetConditionMask Lib "kernel32" (ByVal dwlConditionMask As Currency, ByVal dwTypeBitMask As Long, ByVal dwConditionMask As Byte) As Currency
Private Declare Function VerifyVersionInfoW Lib "kernel32" (ByRef lpVersionInfo As Any, ByVal dwTypeMask As Long, ByVal dwlConditionMask As Currency) As Long
Private Const VER_PRODUCT_TYPE As Long = &H80&
Private Const VER_GREATER_EQUAL As Long = 3
Private Const VER_EQUAL As Long = 1
Private Const VER_MAJORVERSION As Long = &H2
Private Const VER_MINORVERSION As Long = &H1
Private Const VER_SERVICEPACKMAJOR As Long = &H20
Private Const VER_NT_WORKSTATION As Long = 1
Public Function IsWindowsVersionOrGreater(ByVal wMajorVersion As Integer, _
ByVal wMinorVersion As Integer, _
ByVal wServicePackMajor As Integer, _
Optional ByVal dwBuild As Long) As Boolean
' Dim osvi As TOSVERSIONINFOEXW
' osvi.dwOSVersionInfoSize = LenB(osvi)
'
' Dim dwlConditionMask As Currency
' dwlConditionMask = VerSetConditionMask( _
' VerSetConditionMask( _
' VerSetConditionMask( _
' 0, VER_MAJORVERSION, VER_GREATER_EQUAL), _
' VER_MINORVERSION, VER_GREATER_EQUAL), _
' VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL)
'
' osvi.dwMajorVersion = wMajorVersion
' osvi.dwMinorVersion = wMinorVersion
' osvi.wServicePackMajor = wServicePackMajor
'
' IsWindowsVersionOrGreater = VerifyVersionInfoW( _
' osvi, _
' VER_MAJORVERSION Or VER_MINORVERSION Or VER_SERVICEPACKMAJOR, _
' dwlConditionMask)
Dim verInfo As TOSVERSIONINFOEXW 'RTL_OSVERSIONINFOEXW
verInfo.dwOSVersionInfoSize = LenB(verInfo)
' Calling RtlGetVersion directly is faster and doesn't depend on
' a manifest or minimum subsystem. It will still lie if running
' with compatibility shim.
If RtlGetVersion(verInfo) = 0 Then
With verInfo
Select Case True
Case .dwMajorVersion > wMajorVersion: IsWindowsVersionOrGreater = True
Case .dwMajorVersion < wMajorVersion: IsWindowsVersionOrGreater = False
Case .dwMinorVersion > wMinorVersion: IsWindowsVersionOrGreater = True
Case .dwMinorVersion < wMinorVersion: IsWindowsVersionOrGreater = False
Case .wServicePackMajor > wServicePackMajor: IsWindowsVersionOrGreater = True
Case .wServicePackMajor < wServicePackMajor: IsWindowsVersionOrGreater = False
Case .dwBuildNumber >= dwBuild: IsWindowsVersionOrGreater = True
End Select
End With
End If
End Function
Private Function HIBYTE(ByVal W As Integer) As Byte
HIBYTE = (W And &H7FFF) \ &H100
If W < 0 Then HIBYTE = HIBYTE Or &H80
End Function
Private Function LOBYTE(ByVal W As Integer) As Byte
LOBYTE = W And &HFF
End Function
Public Function IsWindowsXPOrGreater() As Boolean
IsWindowsXPOrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINXP), LOBYTE(WIN32_WINNT_WINXP), 0)
End Function
Public Function IsWindowsXPSP1OrGreater() As Boolean
IsWindowsXPSP1OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINXP), LOBYTE(WIN32_WINNT_WINXP), 1)
End Function
Public Function IsWindowsXPSP2OrGreater() As Boolean
IsWindowsXPSP2OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINXP), LOBYTE(WIN32_WINNT_WINXP), 2)
End Function
Public Function IsWindowsXPSP3OrGreater() As Boolean
IsWindowsXPSP3OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINXP), LOBYTE(WIN32_WINNT_WINXP), 3)
End Function
Public Function IsWindowsVistaOrGreater() As Boolean
IsWindowsVistaOrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_VISTA), LOBYTE(WIN32_WINNT_VISTA), 0)
End Function
Public Function IsWindowsVistaSP1OrGreater() As Boolean
IsWindowsVistaSP1OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_VISTA), LOBYTE(WIN32_WINNT_VISTA), 1)
End Function
Public Function IsWindowsVistaSP2OrGreater() As Boolean
IsWindowsVistaSP2OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_VISTA), LOBYTE(WIN32_WINNT_VISTA), 2)
End Function
Public Function IsWindows7OrGreater() As Boolean
IsWindows7OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN7), LOBYTE(WIN32_WINNT_WIN7), 0)
End Function
Public Function IsWindows7SP1OrGreater() As Boolean
IsWindows7SP1OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN7), LOBYTE(WIN32_WINNT_WIN7), 1)
End Function
Public Function IsWindows8OrGreater() As Boolean
IsWindows8OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN8), LOBYTE(WIN32_WINNT_WIN8), 0)
End Function
Public Function IsWindows8Point1OrGreater() As Boolean
IsWindows8Point1OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WINBLUE), LOBYTE(WIN32_WINNT_WINBLUE), 0)
End Function
Public Function IsWindows10OrGreater() As Boolean
IsWindows10OrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN10), LOBYTE(WIN32_WINNT_WIN10), 0)
End Function
Public Function IsWindows10AnniversaryOrGreater() As Boolean
IsWindows10AnniversaryOrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN10AU), LOBYTE(WIN32_WINNT_WIN10AU), 0, 14393)
End Function
Public Function IsWindows10CreatorsOrGreater() As Boolean
IsWindows10CreatorsOrGreater = IsWindowsVersionOrGreater(HIBYTE(WIN32_WINNT_WIN10CU), LOBYTE(WIN32_WINNT_WIN10CU), 0, 15063)
End Function
Public Function IsWindowsServer() As Boolean
Dim osvi As TOSVERSIONINFOEXW
osvi.dwOSVersionInfoSize = LenB(osvi)
osvi.wProductType = VER_NT_WORKSTATION
Dim dwlConditionMask As Currency
dwlConditionMask = VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL)
IsWindowsServer = Not CBool(VerifyVersionInfoW(osvi, VER_PRODUCT_TYPE, dwlConditionMask))
End Function
Last edited by DEXWERX; Jun 23rd, 2017 at 01:07 PM.
Reason: replaced LongLong with Currency
-
Jun 23rd, 2017, 08:37 AM
#3
Thread Starter
Lively Member
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
Damn, the MSDN writers should mention that a function is inline explicitly and noticeably in the function topic - not only with a word "inline" in a sentence in the Example section.
-
Jun 23rd, 2017, 08:39 AM
#4
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
not only that - but VerifyVersionInfoW is subject to the same Manifest shenanigans that caused us to start calling RtlGetVersion in the first place.
https://stackoverflow.com/questions/...-on-windows-10
-
Jun 23rd, 2017, 09:03 AM
#5
Thread Starter
Lively Member
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
Do you want to say that the best way to determine whether we are in Win10 is still RtlGetVersion? It seems the following code I have been using for a couple of years has never let me down:
Code:
Private Declare Function RtlGetVersion Lib "NTDLL" (ByRef lpVersionInformation As Long) As Long
Public Sub NativeGetVersion(ByRef plMajorVer As Long, ByRef plMinorVer As Long)
Dim tOSVw(&H54) As Long
tOSVw(0) = &H54 * &H4
RtlGetVersion tOSVw(0)
plMajorVer = tOSVw(1)
plMinorVer = tOSVw(2)
End Sub
Dim lOSMajorVer As Long
Dim lOSMinorVer As Long
NativeGetVersion lOSMajorVer, lOSMinorVer
bIsWin10 = (lOSMajorVer >= 10)
-
Jun 23rd, 2017, 09:46 AM
#6
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
Originally Posted by wisekat
Do you want to say that the best way to determine whether we are in Win10 is still RtlGetVersion? It seems the following code I have been using for a couple of years has never let me down:
Code:
Private Declare Function RtlGetVersion Lib "NTDLL" (ByRef lpVersionInformation As Long) As Long
Public Sub NativeGetVersion(ByRef plMajorVer As Long, ByRef plMinorVer As Long)
Dim tOSVw(&H54) As Long
tOSVw(0) = &H54 * &H4
RtlGetVersion tOSVw(0)
plMajorVer = tOSVw(1)
plMinorVer = tOSVw(2)
End Sub
Dim lOSMajorVer As Long
Dim lOSMinorVer As Long
NativeGetVersion lOSMajorVer, lOSMinorVer
bIsWin10 = (lOSMajorVer >= 10)
Definitely,
RtlGetVersion has been the most reliable across all OS's and it's not dependent on minimum subsystem or manifest.
Even the code I posted above has a faster version commented out that calls RtlGetVersion.
I just don't know if it's legal to call from a Windows Store App, I thought some APIs are restricted, but if you're targeting the store, you can manifest/subsystem for windows 10 anyway.
-
Jun 23rd, 2017, 09:58 AM
#7
Thread Starter
Lively Member
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
Just a comment regarding one situation when RtlGetVersion can lie - or at least, I though so in the beginning
Today RtlGetVersion returned 6 in the OSMajorVersion parameter on my pc with Windows 10 Pro. I thought Microsoft had changed something again with the Creators Update, but after some thinking I found the source of the problem:
Most likely, that's right if RtlGetVersion returns the OS version number taking into account this compatibility settings...
-
Jun 23rd, 2017, 11:57 AM
#8
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
Originally Posted by wisekat
Damn, the MSDN writers should mention that a function is inline explicitly and noticeably in the function topic - not only with a word "inline" in a sentence in the Example section.
They did mention it,
The inline functions defined in the VersionHelpers.h header file let you verify the operating system version by returning a Boolean value when testing for a version of Windows.
If you want to pinpoint a version you can use IsWindowsVersionOrGreater
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
Microsoft MVP 2006-2011
Office Development FAQ (C#, VB.NET, VB 6, VBA)
Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
If a post has helped you then Please Rate it!
• Reps & Rating Posts • VS.NET on Vista • Multiple .NET Framework Versions • Office Primary Interop Assemblies • VB/Office Guru™ Word SpellChecker™.NET • VB/Office Guru™ Word SpellChecker™ VB6 • VB.NET Attributes Ex. • Outlook Global Address List • API Viewer utility • .NET API Viewer Utility •
System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6
-
Jun 23rd, 2017, 12:16 PM
#9
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
Originally Posted by RobDog888
a translation of IsWindowsVersionOrGreater can also be found in post #2
-
Jun 23rd, 2017, 12:19 PM
#10
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
Originally Posted by DEXWERX
a translation of IsWindowsVersionOrGreater can also be found in post #2
My oversight,
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
Microsoft MVP 2006-2011
Office Development FAQ (C#, VB.NET, VB 6, VBA)
Senior Jedi Software Engineer MCP (VB 6 & .NET), BSEE, CET
If a post has helped you then Please Rate it!
• Reps & Rating Posts • VS.NET on Vista • Multiple .NET Framework Versions • Office Primary Interop Assemblies • VB/Office Guru™ Word SpellChecker™.NET • VB/Office Guru™ Word SpellChecker™ VB6 • VB.NET Attributes Ex. • Outlook Global Address List • API Viewer utility • .NET API Viewer Utility •
System: Intel i7 6850K, Geforce GTX1060, Samsung M.2 1 TB & SATA 500 GB, 32 GBs DDR4 3300 Quad Channel RAM, 2 Viewsonic 24" LCDs, Windows 10, Office 2016, VS 2019, VB6 SP6
-
Jun 23rd, 2017, 01:17 PM
#11
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
This is the one I use, especially when I want to circumvent any shims/compatibility settings I've got:
Code:
Public Function WindowsVersion() As Long
'
' This is independent of any manifest or any compatibility settings.
'
' OS WindowsVersion return
' Windows 10 100
' Windows 8.1 63
' Windows 8.0 62
' Windows 7 61
' Windows Vista 60
' Windows XP 51
' Windows 2000 50
' -1 failed.
Static lVersion As Long
Dim SystemSet As Object
Dim System As Object
Dim s As String
Dim i As Long
'
If lVersion Then
WindowsVersion = lVersion
Exit Function
End If
'
On Error Resume Next
Set SystemSet = GetObject("winmgmts:").InstancesOf("Win32_OperatingSystem")
For Each System In SystemSet: s = System.Version: Next
'
i = InStr(s, ".")
s = Left$(s, i - 1) & Mid$(s, i + 1)
i = InStr(s, ".")
If i Then s = Left$(s, i - 1)
lVersion = Val(s)
WindowsVersion = lVersion
On Error GoTo 0
End Function
And it works equally well in the IDE as a compiled program.
Enjoy,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
-
Feb 8th, 2019, 06:13 PM
#12
New Member
Re: Calling IsWindows10OrGreater from VB6 in Windows 10
Originally Posted by Elroy
This is the one I use, especially when I want to circumvent any shims/compatibility settings I've got:
Code:
Public Function WindowsVersion() As Long
'
' This is independent of any manifest or any compatibility settings.
'
' OS WindowsVersion return
' Windows 10 100
' Windows 8.1 63
' Windows 8.0 62
' Windows 7 61
' Windows Vista 60
' Windows XP 51
' Windows 2000 50
' -1 failed.
Static lVersion As Long
Dim SystemSet As Object
Dim System As Object
Dim s As String
Dim i As Long
'
If lVersion Then
WindowsVersion = lVersion
Exit Function
End If
'
On Error Resume Next
Set SystemSet = GetObject("winmgmts:").InstancesOf("Win32_OperatingSystem")
For Each System In SystemSet: s = System.Version: Next
'
i = InStr(s, ".")
s = Left$(s, i - 1) & Mid$(s, i + 1)
i = InStr(s, ".")
If i Then s = Left$(s, i - 1)
lVersion = Val(s)
WindowsVersion = lVersion
On Error GoTo 0
End Function
And it works equally well in the IDE as a compiled program.
Enjoy,
Elroy
This is great Elroy, works like a champ from my VB6 app. Simple, yet elegant!
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|