Based on this post for changing the output color of command prompt text in Windows 10, I'm looking for the best way to detect the OS version in a batch file IF statement.
How to echo with different colors in the Windows command line
From my understanding, colorized text was added in Windows 10 Threshold 2 November 18, 2015 (10.0.10586.11)
In Windows 10 version history, up until the Version 1607 (Anniversary Update), there was a major.minor.build.revision numbering scheme so I want the detection to be very granular.
https://en.wikipedia.org/wiki/Windows_10_version_history
I found this post which compares major.minor.build to a user input, but can't wrap my head around what it's doing for my needs.
https://github.com/LogicDaemon/PersonalUseScripts/blob/c3346df9c7c0f57b584b5c0238b8e8b76096c42c/cmd/superuser%20q%20891742/CheckWinVer.cmd
So based on that information, I'm trying to compare the detected version of windows to 10.0.10586.11 in a batch file.
If its greater than or equal to that version, colorize the text, if not use standard formatting.
This was my first attempt to colorize text in an IF statement. Although this appeared to work in Windows 10, it didn't work in Windows 8.1 because string "10." is less than "6.3"
FOR /F "tokens=4-5 delims=. " %%i in ('ver') DO SET Version=%%i.%%j
IF "%Version%" GEQ "10.0" (echo [92mHere is my text in green.[0m) ELSE (echo Here is my text)
Note the required escape characters are missing in the above sample
Compare numeric values instead of strings (e.g. Windows 8.1 returns 603):
FOR /F "tokens=4-5 delims=. " %%i in ('ver') DO SET /A _Version=%%i*100+%%j
IF %_Version% GEQ 1000 (echo [92mHere is my text in green.[0m) ELSE (echo Here is my text)
Edit. Instead of wikipedia, I'd use a primary source Windows 10 release information on Microsoft’s TechNet site.
FOR /F "tokens=4-7 delims=[]. " %%i in ('ver') DO (
SET /A _MajorMinor = %%i * 100 + %%j
set /A _Build = %%k0 /10
set /A _Revision = %%l0 /10
)
set "_AE=" AE like Ansi Escape
IF %_MajorMinor% GEQ 1000 if %_Build% GTR 10586 ( set "_AE=Yes" ) else (
if %_Build% EQU 10586 if %_Revision% GEQ 11 set "_AE=Yes" )
rem use the _AE flag
if defined _AE (echo [92mHere is my text in green.[0m) ELSE (echo Here is my text)
Used nested IFs (effective as of logical AND).
The set /A _Revision = %%l0 /10 construct used to avoid Missing operator on Windows 8 where the 7th token %%l results to an empty string.
I am trying to retrieve the Microsoft Office version using the following command:
reg query "HKEY_CLASSES_ROOT\Word.Application\CurVer"
this returns the following output:
HKEY_CLASSES_ROOT\Word.Application\CurVer
(Default) REG_SZ Word.Application.15
I need to parse the output and match the version using the following table and paste the final version into a text file.
Office 97 - 7.0
Office 98 - 8.0
Office 2000 - 9.0
Office XP - 10.0
Office 2003 - 11.0
Office 2007 - 12.0
Office 2010 - 14.0
Office 2013 - 15.0
Office 2016 - 16.0
How do i go about this?
I provided a similar answer in your previous, although seemingly ignored, question on Outlook.
There may be a way using the registry, (although only for Office 2007 onwards):
#Echo Off
If "%PROCESSOR_ARCHITECTURE:~-2%"=="86" (If Defined PROCESSOR_ARCHITEW6432 (
Set "KEY=\Wow6432Node" & Set "MWB=64") Else (Set "MWB=32" & Set "MOB=32"
)) Else Set "MWB=64"
Set "KEY=HKLM\Software%KEY%\Microsoft\Windows\CurrentVersion\Uninstall"
Set "GUID="
For /F "Delims=" %%A In ('Reg Query %KEY% /K /F "*-001B-*0FF1CE}"') Do (
If Not Defined GUID Set "GUID=%%~nxA")
If Not "%GUID:~-1%"=="}" Set "GUID="
If Not Defined GUID (Echo= Unable to find Office Product & GoTo EndIt)
If %GUID:~4,1% Equ 4 Set "IOV=10" Else (If %GUID:~4,1% Equ 2 (Set "IOV=07"
If Not Defined MOB Set "MOB=32") Else (If %GUID:~4,1% Equ 5 (Set "IOV=13"
) Else (If %GUID:~4,1% Equ 6 Set "IOV=16")))
If Not Defined IOV (Echo= Unknown Office version on your %MWB%-bit OS
GoTo EndIt)
If Not Defined MOB Set "MOB=32"
If %GUID:~20,1% Equ 1 Set "MOB=64"
Echo=&Echo= Office 20%IOV% %MOB%-bit Product installed on a %MWB%-bit OS
:EndIt
Timeout 5 1>Nul
This has not been tested because I have never been able to justify the cost of any Microsoft Office product.
#echo off
for /f "tokens=5* skip=1 delims=. " %%a in ('reg query "HKEY_CLASSES_ROOT\Word.Application\CurVer"') do set "wver=%%a.0"
for %%# in ("Office 97-7.0" "Office 98-8.0" "Office 2000-9.0" "Office XP-10.0" "Office 2003-11.0" "Office 2007-12.0" "Office 2010-14.0" "Office 2013-15.0" "Office 2016-16.0") do (
for /f "tokens=1* delims=-" %%a in ("%%~#") do (
if %%b equ %wver% (
set ov=%%a
)
)
)
echo %ov%
But you have pretty old versions of the MS Office which can be installed only on windows xp (or even older versions of windows) where the reg command is not available. So you can also check this which uses FTYPE command to determine the office version
I am checking for the OS version using command prompt.
I am using following code to get the version number
systeminfo | findstr /B /c:"OS Version"
Output
For Windows Server 2003
OS Version: 5.2.3790 Service Pack 2 Build 3790
For Windows 7
OS Version: 6.1.7601 Service Pack 1 Build 7601
But I am not sure how can I have Major version number (First digit of version)
How can I get the major version number OR
If can I check if the version numbers first char is 5 OR 6
You could pipe the output again through FINDSTR, for example:
systeminfo | findstr /B /c:"OS Version" | findstr /c:" 6."
And then check the ERRORLEVEL returned to see if 6. was present in the returned string.
NOTE:
I've put a space at the beginning of the second string to try and ensure that it doesn't match against anything else that might be stuffed into the output from systeminfo on an "OS Version" line
This is really brittle as it relies on the format of the returned text from systeminfo
There's doubtless a better way to do this with the VER command
For a really robust way of doing this that is independent of the format of the text returned by systeminfo/ver, consider writing a small program in C# (Express Edition is free) that looks at the System.Environment.OSVersion property and sets an error level for you as this would be string parse-free (and thus a lot less likely to break)!
here is a snippet using ver.exe :
for /f "tokens=4 delims=. " %%i in ('ver') do set majorversion=%%i
I would use the ver command instead of systeminfo. My Windows 7 machine reports:
Microsoft Windows [Version 6.1.7601]
The following batch script snippet will define a variable containing the primary version number:
for /f "tokens=2 delims=[]" %%A in ('ver') do for /f "tokens=2 delims=. " %%B in ("%%A") do set "majorVersion=%%B"
I have a (test) batch file with this code
If Exist "C:\Users\All Users\ntuser.dat" Goto Win 7
If Exist "C:\Documents and Settings\All Users\ntuser.dat" Goto Win XP
:Win 7
will write here the parameters which'll run on win7
C:\w7\test.txt
:Win XP
will write here the parameters which'll run on winxp
and so the same with other os + os architecture
it's working, but i need to add more os identify options..
I need that batch file to identify os version, architecture (Windows 2003R2 x64 only, Windows Xp x32 and x64, Windows Vista x32 and x64, Windows 7 x32 and x64, Windows 8 x32 and x64)
Thank you very much in Advanced!
there is a nice solution from Aacini here on SO, but can't find it now and post it from my "library":
#echo off
setlocal EnableDelayedExpansion
::Identify OS
for /F "delims=" %%a in ('ver') do set ver=%%a
set Version=
for %%a in (95=95 98=98 ME=ME NT=NT 2000=2000 5.1.=XP 5.2.=2003 6.0.=Vista 6.1.=7 6.2.=8) do (
if "!Version!" equ "this" (
set Version=Windows %%a
) else if "!ver: %%a=!" neq "%ver%" (
set Version=this
)
)
::Identify bit
if exist "%SYSTEMDRIVE%\Program Files (x86)" (
set Type=64 bit
) else (
set Type=32 bit
)
::Display result
echo %Version% %Type%
goto :eof
::Goto right version
goto %Version: =_%
:Windows_8
echo Windows 8
:Windows_7
echo Windows 7
© Aacini at dostips
Just use WMIC from command line or batch file. Much easier, shorter and you can parse it.
wmic OS get OSArchitecture,caption
Believe it or not, my installer is so old that it doesn't have an option to detect the 64-bit version of Windows.
Is there a Windows DLL call or (even better) an environment variable that would give that information for Windows XP and Windows Vista?
One possible solution
I see that Wikipedia states that the 64-bit version of Windows XP and Windows Vista have a unique environment variable: %ProgramW6432%, so I'm guessing that'd be empty on 32-bit Windows.
This variable points to Program Files directory, which stores all the installed program of Windows and others. The default on English-language systems is C:\Program Files. In 64-bit editions of Windows (XP, 2003, Vista), there are also %ProgramFiles(x86)% which defaults to C:\Program Files (x86) and %ProgramW6432% which defaults to C:\Program Files. The %ProgramFiles% itself depends on whether the process requesting the environment variable is itself 32-bit or 64-bit (this is caused by Windows-on-Windows 64-bit redirection).
To check for a 64-bit version of Windows in a command box, I use the following template:
test.bat:
#echo off
if defined ProgramFiles(x86) (
#echo yes
#echo Some 64-bit work
) else (
#echo no
#echo Some 32-bit work
)
ProgramFiles(x86) is an environment variable automatically defined by cmd.exe (both 32-bit and 64-bit versions) on Windows 64-bit machines only.
Here is some Delphi code to check whether your program is running on a 64 bit operating system:
function Is64BitOS: Boolean;
{$IFNDEF WIN64}
type
TIsWow64Process = function(Handle:THandle; var IsWow64 : BOOL) : BOOL; stdcall;
var
hKernel32 : Integer;
IsWow64Process : TIsWow64Process;
IsWow64 : BOOL;
{$ENDIF}
begin
{$IFDEF WIN64}
//We're a 64-bit application; obviously we're running on 64-bit Windows.
Result := True;
{$ELSE}
// We can check if the operating system is 64-bit by checking whether
// we are running under Wow64 (we are 32-bit code). We must check if this
// function is implemented before we call it, because some older 32-bit
// versions of kernel32.dll (eg. Windows 2000) don't know about it.
// See "IsWow64Process", http://msdn.microsoft.com/en-us/library/ms684139.aspx
Result := False;
hKernel32 := LoadLibrary('kernel32.dll');
if hKernel32 = 0 then RaiseLastOSError;
try
#IsWow64Process := GetProcAddress(hkernel32, 'IsWow64Process');
if Assigned(IsWow64Process) then begin
if (IsWow64Process(GetCurrentProcess, IsWow64)) then begin
Result := IsWow64;
end
else RaiseLastOSError;
end;
finally
FreeLibrary(hKernel32);
end;
{$ENDIf}
end;
From a batch script:
IF PROCESSOR_ARCHITECTURE == x86 AND
PROCESSOR_ARCHITEW6432 NOT DEFINED THEN
// OS is 32bit
ELSE
// OS is 64bit
END IF
Using Windows API:
if (GetSystemWow64Directory(Directory, MaxDirectory) > 0)
// OS is 64bit
else
// OS is 32bit
Sources:
HOWTO: Detect Process Bitness
GetSystemWow64Directory function
I tested the solution I suggested in my question:
Tested for Windows Environment Variable: ProgramW6432
If it's non empty then it's 64 bit Windows.W
See the batch script listed in How To Check If Computer Is Running A 32 Bit or 64 Bit Operating System. It also includes instructions for checking this from the Registry:
You can use the following registry location to check if computer is running 32 or 64 bit of Windows operating system:
HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0
You will see the following registry entries in the right pane:
Identifier REG_SZ x86 Family 6 Model 14 Stepping 12
Platform ID REG_DWORD 0x00000020(32)
The above “x86” and “0x00000020(32)” indicate that the operating system version is 32 bit.
If you can make API calls, try using GetProcAddress / GetModuleHandle to check for the existence of IsWow64Process which is only present in Windows OS that have 64-bit versions.
You could also try the ProgramFiles(x86) environment variable used in Vista/2008 for backwards compatibility, but I'm not 100% sure about XP-64 or 2003-64.
Good luck!
I used this within a login script to detect 64 bit Windows
if "%ProgramW6432%" == "%ProgramFiles%" goto is64flag
For a VBScript / WMI one-liner that retrieves the actuals bits number (32 or 64) of the OS or the Hardware, take a look at http://csi-windows.com/toolkit/csi-getosbits
I don't know what language you're using, but .NET has the environment variable PROCESSOR_ARCHITEW6432 if the OS is 64-bit.
If all you want to know is whether your application is running 32-bit or 64-bit, you can check IntPtr.Size. It will be 4 if running in 32-bit mode and 8 if running in 64-bit mode.
I want to add what I use in shell scripts (but can easily be used in any language) here.
The reason is, that some of the solutions here don't work an WoW64, some use things not really meant for that (checking if there is a *(x86) folder) or don't work in cmd scripts.
I feel, this is the "proper" way to do it, and should be safe even in future versions of Windows.
#echo off
if /i %processor_architecture%==AMD64 GOTO AMD64
if /i %PROCESSOR_ARCHITEW6432%==AMD64 GOTO AMD64
rem only defined in WoW64 processes
if /i %processor_architecture%==x86 GOTO x86
GOTO ERR
:AMD64
rem do amd64 stuff
GOTO EXEC
:x86
rem do x86 stuff
GOTO EXEC
:EXEC
rem do arch independent stuff
GOTO END
:ERR
rem I feel there should always be a proper error-path!
#echo Unsupported architecture!
pause
:END
A lot of answers mention calling IsWoW64Process() or related functions. This is not the correct way. You should use GetNativeSystemInfo() which was designed for this purpose. Here's an example:
SYSTEM_INFO info;
GetNativeSystemInfo(&info);
if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
// It's a 64-bit OS
}
Also see:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724340%28v=vs.85%29.aspx
I don't know on which Windows version it exists, but on Windows Vista and later this runs:
Function Is64Bit As Boolean
Dim x64 As Boolean = System.Environment.Is64BitOperatingSystem
If x64 Then
Return true
Else
Return false
End If
End Function
In C#:
public bool Is64bit() {
return Marshal.SizeOf(typeof(IntPtr)) == 8;
}
In VB.NET:
Public Function Is64bit() As Boolean
If Marshal.SizeOf(GetType(IntPtr)) = 8 Then Return True
Return False
End Function
I use this:
#echo off
if "%PROCESSOR_ARCHITECTURE%"=="AMD64" (
echo 64 BIT
) else (
echo 32 BIT
)
It works on Windows XP, tested it on Windows XP Professional Both 64 bit and 32 bit.
I know this is ancient but, here's what I use to detect Win764
On Error Resume Next
Set objWSHShell = CreateObject("WScript.Shell")
strWinVer = objWSHShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\BuildLabEx")
If len(strWinVer) > 0 Then
arrWinVer = Split(strWinVer,".")
strWinVer = arrWinVer(2)
End If
Select Case strWinVer
Case "x86fre"
strWinVer = "Win7"
Case "amd64fre"
strWinVer = "Win7 64-bit"
Case Else
objWSHShell.Popup("OS Not Recognized")
WScript.Quit
End Select
I tested the following batch file on Windows 7 x64/x86 and Windows XP x86 and it's fine, but I haven't tried Windows XP x64 yet, but this will probably work:
If Defined ProgramW6432 (Do x64 stuff or end if you are aiming for x86) else (Do x86 stuff or end if you are aiming for x64)
Using Windows Powershell, if the following expression returns true, then it's a 64 bit OS:
(([Array](Get-WmiObject -Class Win32_Processor | Select-Object AddressWidth))[0].AddressWidth -eq 64)
This was taken and modified from: http://depsharee.blogspot.com/2011/06/how-do-detect-operating-system.html (Method #3). I've tested this on Win7 64 bit (in both 32 and 64 bit PowerShell sessions), and XP 32 bit.
The best way is surely just to check whether there are two program files directories, 'Program Files'and 'Program Files (x86)'
The advantage of this method is you can do it when the o/s is not running, for instance if the machine has failed to start and you wish to reinstall the operating system
Interestingly, if I use
get-wmiobject -class Win32_Environment -filter "Name='PROCESSOR_ARCHITECTURE'"
I get AMD64 in both 32-bit and 64-bit ISE (on Win7 64-bit).
Another way created by eGerman that uses PE numbers of compiled executables (does not rely on registry records or environment variables):
#echo off &setlocal
call :getPETarget "%SystemRoot%\explorer.exe"
if "%=ExitCode%" EQU "00008664" (
echo x64
) else (
if "%=ExitCode%" EQU "0000014C" (
echo x32
) else (
echo undefined
)
)
goto :eof
:getPETarget FilePath
:: ~~~~~~~~~~~~~~~~~~~~~~
:: Errorlevel
:: 0 Success
:: 1 File Not Found
:: 2 Wrong Magic Number
:: 3 Out Of Scope
:: 4 No PE File
:: ~~~~~~~~~~~~~~~~~~~~~~
:: =ExitCode
:: CPU identifier
setlocal DisableDelayedExpansion
set "File=%~1"
set Cmp="%temp%\%random%.%random%.1KB"
set Dmp="%temp%\%random%.%random%.dmp"
REM write 1024 times 'A' into a temporary file
if exist "%File%" (
>%Cmp% (
for /l %%i in (1 1 32) do <nul set /p "=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
)
setlocal EnableDelayedExpansion
) else (endlocal &cmd /c exit 0 &exit /b 1)
REM generate a HEX dump of the executable file (first 1024 Bytes)
set "X=1"
>!Dmp! (
for /f "skip=1 tokens=1,2 delims=: " %%i in ('fc /b "!File!" !Cmp!^|findstr /vbi "FC:"') do (
set /a "Y=0x%%i"
for /l %%k in (!X! 1 !Y!) do echo 41
set /a "X=Y+2"
echo %%j
)
)
del !Cmp!
REM read certain values out of the HEX dump
set "err="
<!Dmp! (
set /p "A="
set /p "B="
REM magic number has to be "MZ"
if "!A!!B!" neq "4D5A" (set "err=2") else (
REM skip next 58 bytes
for /l %%i in (3 1 60) do set /p "="
REM bytes 61-64 contain the offset to the PE header in little endian order
set /p "C="
set /p "D="
set /p "E="
set /p "F="
REM check if the beginning of the PE header is part of the HEX dump
if 0x!F!!E!!D!!C! lss 1 (set "err=3") else (
if 0x!F!!E!!D!!C! gtr 1018 (set "err=3") else (
REM skip the offset to the PE header
for /l %%i in (65 1 0x!F!!E!!D!!C!) do set /p "="
REM next 4 bytes have to contain the signature of the PE header
set /p "G="
set /p "H="
set /p "I="
set /p "J="
REM next 2 bytes contain the CPU identifier in little endian order
set /p "K="
set /p "L="
)
)
)
)
del !Dmp!
if defined err (endlocal &endlocal &cmd /c exit 0 &exit /b %err%)
REM was the signature ("PE\0\0") of the PE header found
if "%G%%H%%I%%J%"=="50450000" (
REM calculate the decimal value of the CPU identifier
set /a "CPUID=0x%L%%K%"
) else (endlocal &endlocal &cmd /c exit 0 &exit /b 4)
endlocal &endlocal &cmd /c exit %CPUID% &exit /b 0
Here is a simpler method for batch scripts
#echo off
goto %PROCESSOR_ARCHITECTURE%
:AMD64
echo AMD64
goto :EOF
:x86
echo x86
goto :EOF
Answer for Newer Versions of Windows
Today, I posted some code on another question and an explanation of how to do this with IsWow64Process2 for Windows 10 version 1511 or later and Windows Server 2016. Additionally, the code determines if the process is 32 or 64 bit and whether the process is running under the WOW64 emulator.
One of the main reasons I have posted the answer is because while there were several suggestions to use IsWow64Process2, no code that I saw showed how.
Please see the answer here: https://stackoverflow.com/a/59377888/1691559
You can use the module from npm called #wider/utils_where-am-i. This runs in any javascript environment on a windows machine and elsewhere such as linux. On a windows machine it delivers an object which has { os: 'win32' } or { os : 'win64' }. It can run as legacy plain javascript say in wshell, in classic ASP or nodeJS
Check the Registry for the existence of HKLM\SOFTWARE\Wow6432Node
- If it's there, the system is 64-bit
- 32-bit, otherwise.