wraithdu Posted October 7, 2009 Share Posted October 7, 2009 This should be a future proof OS version compare function. I've been burned a few times with old scripts using @OSVersion to do version detection when a new OS (like Windows 7) comes out, since @OSVersion tests are usually done explicitly (If @OSVersion = "WIN_VISTA"...). I've had this laying around for a bit but didn't release it due to a bug in AutoIt < 3.3.1.0. But then it meant it would only work with >= 3.3.1.0, and older versions of AutoIt would get incorrect results, but no errors. Many people still run old versions of AutoIt so that's not cool. I came up with a suitable workaround today so here it is. It can easily be extended to test all kinds of OS properties: Build Number, Platform ID, Product Type, Suite Name. But this is solely aimed at testing version info: major and minor version, service pack major and minor version. In fact according to MSDN, all four of these must be tested at once, not individually. Usage is pretty straight forward, decide on a test and which version numbers you are interested in. If not @error, 0 means the comparison is false, 1 means the comparison is true. If the function returns @error, check the return: 1 means check @Extended for the source of the error, 2 means GetLastError failed which means the outcome of the function is unknowable. Value of @extended: 1 means the error is from DllCall, 2 means the error is from GetLastError. expandcollapse popup#include-once #cs Windows 7 6.1 Windows Server 2008 R2 6.1 Windows Server 2008 6.0 Windows Vista 6.0 Windows Server 2003 R2 5.2 Windows Server 2003 5.2 Windows XP 5.1 Windows 2000 5.0 #ce ;*** Constants ; dwTypeBitMask Global Const $VER_BUILDNUMBER = 0x0000004 Global Const $VER_MAJORVERSION = 0x0000002 Global Const $VER_MINORVERSION = 0x0000001 Global Const $VER_PLATFORMID = 0x0000008 Global Const $VER_PRODUCT_TYPE = 0x0000080 Global Const $VER_SERVICEPACKMAJOR = 0x0000020 Global Const $VER_SERVICEPACKMINOR = 0x0000010 Global Const $VER_SUITENAME = 0x0000040 ; dwConditionMask Global Const $VER_EQUAL = 1 Global Const $VER_GREATER = 2 Global Const $VER_GREATER_EQUAL = 3 Global Const $VER_LESS = 4 Global Const $VER_LESS_EQUAL = 5 ; if dwTypeBitMask is VER_SUITENAME Global Const $VER_AND = 6 Global Const $VER_OR = 7 ; #FUNCTION# ;=============================================================================== ; ; Name...........: _OsVersionTest ; Description ...: Compares OS Version Info ; Syntax.........: _OsVersionTest($iTest, $osMajor, $osMinor = 0, $spMajor = 0, $spMinor = 0) ; Parameters ....: $iTest - type of test to perform ; $osMajor - OS major version number ; $osMinor - OS minor version number ; $spMajor - service pack major version number ; $spMinor - service pack minor version number ; Return values .: Success - Returns nonzero value if the comparison is true, 0 if it is false ; Failure - Sets @Error ; Return values: ; | 1 - Check @Extended ; | 2 - GetLastError failed, we have no way to know the outcome of the function ; @Extended holds the source of @Error: ; | 1 - DllCall error ; | 2 - Function error from GetLastError ; Author ........: Erik Pilsits ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _OsVersionTest($iTest, $osMajor, $osMinor = 0, $spMajor = 0, $spMinor = 0) Local Const $OSVERSIONINFOEXW = "dword dwOSVersionInfoSize;dword dwMajorVersion;dword dwMinorVersion;dword dwBuildNumber;dword dwPlatformId;" & _ "wchar szCSDVersion[128];ushort wServicePackMajor;ushort wServicePackMinor;ushort wSuiteMask;byte wProductType;byte wReserved" Local $dwlConditionalMask = 0 ; initialize structure Local $OSVI = DllStructCreate($OSVERSIONINFOEXW) DllStructSetData($OSVI, "dwOSVersionInfoSize", DllStructGetSize($OSVI)) ; set data we want to compare DllStructSetData($OSVI, "dwMajorVersion", $osMajor) DllStructSetData($OSVI, "dwMinorVersion", $osMinor) DllStructSetData($OSVI, "wServicePackMajor", $spMajor) DllStructSetData($OSVI, "wServicePackMinor", $spMinor) ; check AutoIt version ; -1 = version 2 is greater...this is bad, DllCall() int64 return was fixed in 3.3.1.0 Local $IsBadAutoIt = (__VersionCompare(@AutoItVersion, "3.3.1.0") = -1) ; initialize and set the mask VerSetConditionMask($VER_MAJORVERSION, $iTest, $dwlConditionalMask, $IsBadAutoIt) VerSetConditionMask($VER_MINORVERSION, $iTest, $dwlConditionalMask, $IsBadAutoIt) VerSetConditionMask($VER_SERVICEPACKMAJOR, $iTest, $dwlConditionalMask, $IsBadAutoIt) VerSetConditionMask($VER_SERVICEPACKMINOR, $iTest, $dwlConditionalMask, $IsBadAutoIt) ; perform test Return VerifyVersionInfo(DllStructGetPtr($OSVI), BitOR($VER_MAJORVERSION, $VER_MINORVERSION, $VER_SERVICEPACKMAJOR, $VER_SERVICEPACKMINOR), $dwlConditionalMask) EndFunc ;;;INTERNAL;;; Func VerSetConditionMask($dwTypeBitMask, $dwConditionMask, ByRef $dwlConditionalMask, $IsBadAutoIt) Local $ret = DllCall("kernel32.dll", "uint64", "VerSetConditionMask", "uint64", $dwlConditionalMask, "dword", $dwTypeBitMask, "byte", $dwConditionMask) If Not @error Then If $IsBadAutoIt Then ; fix for bad DllCall() int64 return value $dwlConditionalMask = _ReOrderULONGLONG($ret[0]) Else $dwlConditionalMask = $ret[0] EndIf EndIf EndFunc Func VerifyVersionInfo($lpVersionInfo, $dwTypeMask, $dwlConditionalMask) Local Const $ERROR_OLD_WIN_VERSION = 1150 ; dwTypeMask is a BitOR'd combination of the conditions we want to test Local $ret = DllCall("kernel32.dll", "int", "VerifyVersionInfoW", "ptr", $lpVersionInfo, "dword", $dwTypeMask, "uint64", $dwlConditionalMask) If Not @error Then ; test for function error If $ret[0] Then Return $ret[0] ; comparison is true Else ; function returned 0, we have to check GetLastError to see if there was an error $ret = DllCall("kernel32.dll", "dword", "GetLastError") If Not @error Then If $ret[0] = $ERROR_OLD_WIN_VERSION Then Return 0 ; no error, the version comparison was false Else Return SetError($ret[0], 2, 1) ; we have a real error EndIf Else Return SetError(1, 0, 2) ; this would suck, but shouldn't happen EndIf EndIf Else Return SetError(@error, 1, 1) ; DllCall error EndIf EndFunc Func _ReOrderULONGLONG($UINT64) Local $s_uint64 = DllStructCreate("uint64") Local $s_ulonglong = DllStructCreate("ulong;ulong", DllStructGetPtr($s_uint64)) DllStructSetData($s_uint64, 1, $UINT64) Local $val = DllStructGetData($s_ulonglong, 1) DllStructSetData($s_ulonglong, 1, DllStructGetData($s_ulonglong, 2)) DllStructSetData($s_ulonglong, 2, $val) Return DllStructGetData($s_uint64, 1) EndFunc ; #FUNCTION# ==================================================================================================================== ; Name...........: _VersionCompare ; Description ...: Compares two file versions for equality ; Syntax.........: _VersionCompare($sVersion1, $sVersion2) ; Parameters ....: $sVersion1 - IN - The first version ; $sVersion2 - IN - The second version ; Return values .: Success - Following Values: ; | 0 - Both versions equal ; | 1 - Version 1 greater ; |-1 - Version 2 greater ; Failure - @error will be set in the event of a catasrophic error ; Author ........: Valik ; Modified.......: ; Remarks .......: This will try to use a numerical comparison but fall back on a lexicographical comparison. ; See @extended for details about which type was performed. ; Related .......: ; Link ..........: ; Example .......: ; =============================================================================================================================== Func __VersionCompare($sVersion1, $sVersion2) If $sVersion1 = $sVersion2 Then Return 0 Local $sep = "." If StringInStr($sVersion1, $sep) = 0 Then $sep = "," Local $aVersion1 = StringSplit($sVersion1, $sep) Local $aVersion2 = StringSplit($sVersion2, $sep) If UBound($aVersion1) <> UBound($aVersion2) Or UBound($aVersion1) = 0 Then ; Compare as strings SetExtended(1) If $sVersion1 > $sVersion2 Then Return 1 ElseIf $sVersion1 < $sVersion2 Then Return -1 EndIf Else For $i = 1 To UBound($aVersion1) - 1 ; Compare this segment as numbers If StringIsDigit($aVersion1[$i]) And StringIsDigit($aVersion2[$i]) Then If Number($aVersion1[$i]) > Number($aVersion2[$i]) Then Return 1 ElseIf Number($aVersion1[$i]) < Number($aVersion2[$i]) Then Return -1 EndIf Else ; Compare the segment as strings SetExtended(1) If $aVersion1[$i] > $aVersion2[$i] Then Return 1 ElseIf $aVersion1[$i] < $aVersion2[$i] Then Return -1 EndIf EndIf Next EndIf ; This point should never be reached Return SetError(2, 0, 0) EndFunc ;==>_VersionCompare Example: ConsoleWrite("Is Vista or Greater: " & _OsVersionTest($VER_GREATER_EQUAL, 6) & @CRLF) ConsoleWrite("Is Win7: " & _OsVersionTest($VER_EQUAL, 6, 1) & @CRLF) ConsoleWrite("Is Less that XP SP2: " & _OsVersionTest($VER_LESS, 5, 1, 2) & @CRLF) Chris_1013 1 Link to comment Share on other sites More sharing options...
supersonic Posted October 22, 2009 Share Posted October 22, 2009 Greate function, good job! That's what I was look for... Link to comment Share on other sites More sharing options...
KaFu Posted November 19, 2009 Share Posted November 19, 2009 Wraithdu, excellent! This one definitely goes to my snippet folder ... Â OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13)Â BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16)Â ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
Rizonetech Posted November 21, 2009 Share Posted November 21, 2009 Great job, thank you! Rizonesoft Open Source Home Scripts: Complete Internet Repair | Development: Rizonesoft SDK Link to comment Share on other sites More sharing options...
KaFu Posted November 22, 2009 Share Posted November 22, 2009 A little derivate , can even be further enhance with the link provided... will do when I'm bored ... expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.0.0 Author: KaFu Script Function: _GetOSVersionEx #ce ---------------------------------------------------------------------------- ; http://www.codeguru.com/cpp/w-p/system/systeminformation/article.php/c8973 #include <array.au3> $aRes = _GetOSVersionEx() _ArrayDisplay($aRes) Func _GetOSVersionEx() Local Const $OSVERSIONINFOEXW = "dword dwOSVersionInfoSize;dword dwMajorVersion;dword dwMinorVersion;dword dwBuildNumber;dword dwPlatformId;" & _ "wchar szCSDVersion[128];ushort wServicePackMajor;ushort wServicePackMinor;ushort wSuiteMask;byte wProductType;byte wReserved" Local $OSVI = DllStructCreate($OSVERSIONINFOEXW) DllStructSetData($OSVI, "dwOSVersionInfoSize", DllStructGetSize($OSVI)) Local $ret = DllCall("kernel32.dll", "int", "GetVersionExW", "ptr", DllStructGetPtr($OSVI)) Local $aReturn[12][2] $aReturn[1][0] = "dwOSVersionInfoSize" $aReturn[2][0] = "dwMajorVersion" $aReturn[3][0] = "dwMinorVersion" $aReturn[4][0] = "dwBuildNumber" $aReturn[5][0] = "dwPlatformId" $aReturn[6][0] = "szCSDVersion" $aReturn[7][0] = "wServicePackMajor" $aReturn[8][0] = "wServicePackMinor" $aReturn[9][0] = "wSuiteMask" $aReturn[10][0] = "wProductType" $aReturn[11][0] = "wReserved" If Not @error Then For $i = 1 To 11 $aReturn[$i][1] = DllStructGetData($OSVI, $i) Next $aReturn[0][0] = $aReturn[2][1] & "." & $aReturn[3][1] & "." & $aReturn[4][1] EndIf Return $aReturn EndFunc ;==>_GetOSVersionEx  OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
supersonic Posted January 10, 2012 Share Posted January 10, 2012 KaFu, I like your UDF a lot and I use it over years... Since AutoIt V3.3.8.0 if I call the UDF with '_OsVersionTest($VER_EQUAL, 6, 1)' it returns 0 - although I'm using MS-Windows 7 (32-Bit, Service Pack 1). Calling the UDF with '_OSVersionTest($VER_GREATER_EQUAL, 6)' returns 1 - just as expected... Please, could you help me? Greets, -supersonic. Link to comment Share on other sites More sharing options...
KaFu Posted January 10, 2012 Share Posted January 10, 2012 Thanks for the courtesy, but it's wraithdu's UDF ... but I'll take a look in the evening, don't have Win7 at hand here, only XP. Â OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2024-Oct-13)Â BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Oct-13) HMW - Hide my Windows (2024-Oct-19) HRC - HotKey Resolution Changer (2012-May-16)Â ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2024-Oct-20) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
supersonic Posted January 10, 2012 Share Posted January 10, 2012 Ohh... Of course, the UDF is done by wraithdu - my fault, I'm sorry for that. So, if wraithdu may also would take a look into it... Link to comment Share on other sites More sharing options...
wraithdu Posted January 10, 2012 Author Share Posted January 10, 2012 Does this forum have a head smack smiley? This'll work... Please read the function header, I've even provided the currently released OS version info. Win7 is version major 6, version minor 1. You, admittedly, are running Service Pack 1. There's a parameter for that. _OsVersionTest($VER_EQUAL, 6, 1, 1) Link to comment Share on other sites More sharing options...
supersonic Posted January 10, 2012 Share Posted January 10, 2012 (edited) Damn... You're right! Thanks for the enlightenment - next time I read more carefully. Edited January 10, 2012 by supersonic Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now