In a post build step i want check if OpenSSH.Client and OpenSSH.Server is installed and install it if it is not there. Checking the installed features with Powershell needs administrative privileges.
Therefore i test the existence of the relevant OpenSSH commands with the following code (extract of long script)
SET /a res=0
SET /a three=3
%windir%\system32\OpenSSH\ssh-keygen.exe /?
echo Errorlevel %ERRORLEVEL%
IF %ERRORLEVEL%==%three% (SET /a res=%res%+1)
%windir%\system32\OpenSSH\ssh-keyscan.exe /?
echo Errorlevel %ERRORLEVEL%
IF %ERRORLEVEL%==%three% (SET /a res=%res%+1)
SET /a check=0
IF %res% == %check% (
echo already installed
goto skipopenSSH
)
echo installation
:skipopenSSH
By checking the existence of the commands no admin privileges are necessary for the check so a normal build will not cause a administrative popup.
On cmd.exe it works fine, but as a post build step in Visual Studio both commands in %windir%\systrem32\OpenSSH are not found, although the variable is expanded to the same c:\Windows\System32\OpenSSH\*.exe as if executed on commandline.
After trying the different find mechanisms which all fail i made a test batch file C:\Windows\System32\OpenSSH\ssh-keyscan.exe /?
which leads to a file not found error if executed as a post build step. So the real question should be: Modifies the visual studio build step commandline the path?
The directory OpenSSH exists in directory %SystemRoot%\System32 with the files ssh-keygen.exe and ssh-keyscan.exe depending on version of Windows 10. The directory %SystemRoot%\System32 is for 64-bit applications on 64-bit Windows. But Visual Studio is a 32-bit application and for that reason 32-bit Windows command processor in directory %SystemRoot%\SysWOW64 is executed to process the batch file with the commands to execute as post build step.
Microsoft documented with WOW64 Implementation Details, File System Redirector and Registry Keys Affected by WOW64 and other documentation pages how Windows on Windows 64 works.
All file system accesses to %windir%\system32\OpenSSH in the batch file processed by 32-bit %SystemRoot%\SysWOW64\cmd.exe being started by 32-bit Visual Studio results in the approach to access %SystemRoot%\SysWOW64\OpenSSH which does not exist at all. There is no subdirectory OpenSSH in Windows system directory for 32-bit applications.
One solution would be using the following code for the batch file executed as post build step.
rem This simple check is for 32-bit Windows and for 64-bit Windows with batch
rem file executed in 64-bit environment by 64-bit Windows command processor.
set FolderSSH=%SystemRoot%\System32\OpenSSH
if exist %FolderSSH%\ssh-keygen.exe if exist %FolderSSH%\ssh-keyscan.exe goto UseOpenSSH
rem This check is for 64-bit Windows with batch file executed
rem in 32-bit environment by 32-bit Windows command processor.
if exist %SystemRoot%\Sysnative\cmd.exe set FolderSSH=%SystemRoot%\Sysnative\OpenSSH
if exist %FolderSSH%\ssh-keygen.exe if exist %FolderSSH%\ssh-keyscan.exe goto UseOpenSSH
rem Search entire system drive on machines without Windows 10 or with older
rem versions of Windows 10 with OpenSSH not installed at all by default.
for /F "delims=" %%I in ('%SystemRoot%\System32\where.exe /R %SystemDrive%\ ssh-keygen.exe 2^>nul') do (
if exist "%%~dpIssh-keyscan.exe" for %%J in ("%%~dpI.") do set "FolderSSH=%%~fJ" & goto UseOpenSSH
)
echo ERROR: ssh-keygen.exe AND ssh-keyscan.exe not found.
rem More code to handle this use case.
goto :EOF
:UseOpenSSH
echo Found ssh-keygen and ssh-keyscan in: "%FolderSSH%"
rem More code to handle this use case with existing SSH tools.
The remarks explain most of the code. The inner FOR loop is used to get the full qualified name of the directory containing ssh-keygen.exe and ssh-keyscan.exe without backslash at end of the folder path to have FolderSSH defined always without a backlash at end for further usage in the batch file.
Please note that it is safe to use %FolderSSH%\ssh-keygen.exe and %FolderSSH%\ssh-keyscan.exe without surrounding " at beginning of the batch script as it is impossible that %FolderSSH% expands to a folder path containing a space or one of these characters &()[]{}^=;!'+,`~.
But "%FolderSSH%\ssh-keygen.exe" and "%FolderSSH%\ssh-keyscan.exe" must be used on the command lines below the label UseOpenSSH because it could happen that WHERE was used to find the two executables anywhere on system drive and for that reason %FolderSSH% could expand now to a folder path containing a space or a character with a special meaning for Windows command processor outside a double quoted argument string.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
echo /?
for /?
goto /?
if /?
rem /?
set /?
where /?
Read also the Microsoft article about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded where command line with using a separate command process started in background with %ComSpec% /c and the command line between ' appended as additional arguments on which 2^>nul became already 2>nul.
The following idea also uses the where.exe command, as mentioned in the comments. This one will search the system drive for ssh-keyscan.exe, and if found will ensure that ssh-keygen.exe is also located there. If both are located in the same place, then it is considered as already installed:
#Set "dirOpenSSH="
#For /F Delims^= %%G In (
'%__AppDir__%where.exe /R %SystemDrive%\ ssh-keyscan.exe 2^>NUL'
)Do #For /F Delims^= %%H In (
'%__AppDir__%where.exe "%%~dpG.":ssh-keygen.exe 2^>NUL'
)Do #Set "dirOpenSSH=%%~dpH"
#If Defined dirOpenSSH (
Echo OpenSSH is available at %dirOpenSSH%.
%__AppDir__%timeout.exe 3 /NoBreak>NUL
GoTo skipopenSSH
)
#Echo OpenSSH is not available, beginning installation.
#%__AppDir__%timeout.exe 3 >NUL
:skipopenSSH
Please note that where.exe and timeout.exe require a minimum OS version of Windows NT 6.x
As your application is currently a 32-bit one, the console session it is using is not accessing the 64-bit locations. To fix that you could replace %__AppDir__%where.exe, with %SystemRoot%\SysNative\where.exe
It is probably worth mentioning that in the versions of windows-10 with OpenSSH part of the base OS, the location, %SYSTEMROOT%\System32\OpenSSH\, should exist in %PATH%, so you should be able to find your files directly using them:
%__AppDir__%where.exe ssh-keygen.exe
%__AppDir__%where.exe ssh-keyscan.exe
For %I In (ssh-keygen.exe) Do #Echo %~$PATH:I
For %I In (ssh-keyscan.exe) Do #Echo %~$PATH:I
I have found on the systems which have upgraded from an earlier version of Windows, that many of the default locations using C:\Windows were replicated, but using %SYSTEMROOT%/%SystemRoot% instead.
In that state, the Where command and For's %~$PATH: failed to locate some items which did exist and should have been found.
Removing the duplicated items, I removed those which were carried over, (those not using variables), although removing either format seems to have worked fine.
Both where and %~$PATH: were then functioning as intended.
As our office upgrades to Window 7, I have been tasked to update the loginscript to work with Windows 7. The creators of said script are long gone, and I am not a batch file expert.
What I am trying to do is determine the OS. As I do some network administration duties, I need to be able to log on to a server without running the login script whereas I will need to the login script to run if I log into a Windows XP or Windows 7 computer.
I found I couldn't use the VER command as Windows 7 and Windows Server 2008 return the exact same results.
This is what I have:
if exist %loginscriptdir%\sysinfo.txt goto setver
if not exist %loginscriptdir%\sysinfo.txt wmic os get name /value > %loginscriptdir%\sysinfo.txt
type %loginscriptdir%\sysinfo.txt > %loginscriptdir%\sysinfo1.txt
:setver
set WinVer=Unknown
set errorlevel=0
If %WinVer% == "Unknown" (
findstr /c:"Windows XP Professional" %loginscriptdir%\sysinfo1.txt
if %errorlevel%==1 set WinVer=XP
) else (
findstr /c:"Windows 7 Enterprise" %loginscriptdir%\sysinfo1.txt
if %errorlevel%==1 set WinVer=Win7
)
set result=false
if %WinVer% == "XP" set result=true
if %WinVer% == "Win7" set result=true
if "%result%" == "false" (
goto skipicon1
Throughout the script, I wrote in breaks to find the values. Example:
REM -----
ECHO "%WinVer%"
ECHO "%result%"
ECHO "%errorlevel%"
ECHO Press any key to continue 4.
pause>null
REM -----
The fourth break comes at the end of the script I pasted above. These are the results:
"Unknown"
"false"
"0"
Press any key to continue 4.
Here you go. This is the best way I've found to get the OS accurately from win2kpro-winserver2k10. It also tells if it's 32/64 bit and what sp is installed but you don't have to. Just check %cap% in this example.
#echo off
setlocal
call :GetOS cap bit sp
echo %cap%%bit% (%sp%)
exit /b
:GetOS caption servicepack
setlocal
set arc=%PROCESSOR_ARCHITECTURE%
set key="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"
for /f "tokens=3*" %%a in (
'reg query %key%^|findstr /i ProductName') do set cap=%%a %%b
for /f "tokens=3*" %%a in (
'reg query %key%^|findstr /i CSDVersion') do set sp=%%a %%b
endlocal & set %1=%cap% & set %2=%arc% & set %3=%sp%
exit /b
The issue with the code is the expansion of the %errorlevel% value. Since it is contained within a scope of parentheses, the value will not be updated till after the scope ends. Meaning that %errorlevel% will always equal its value when the scope began. To fix this you would have to use delayed expansion. setlocal enabledelayedexpansion and !errorlevel!. Here is a StackOverflow post about delayed expansion: Enable and Disable Delayed Expansion, what does it do?
You may just want to use the version detection method shown at ss64.com http://ss64.com/nt/ver.html
Here is the example from ss64.com but simplified:
#echo off
setlocal
:: Get windows Version
for /f "tokens=4,5,6 delims=[.] " %%A in ('ver') do (
set "Major=%%~A"
set "Minor=%%~B"
set "Build=%%~C"
)
if "%Major%.%Minor%"=="5.1" goto WinXP
if "%Major%.%Minor%"=="6.1" goto Win7
echo Unsupported Version Detected "%Major%.%Minor%"
goto End
:WinXP
echo Windows XP Detected
goto End
:Win7
echo Windows 7 or Server 2008 Detected
goto End
:End
endlocal
exit /b 0
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
I'm programming for an embedded device with a NVIDIA Tegra 2 running Windows Embedded Compact 7. My development environment is Microsoft Visual Studio 2008. The boost library and especially the boost-asio package seems to be very helpfull for my needs. Unfortunately I was not able to find a good guide on how to get boost running on Windows Embedded Compact 7. I'd prefere to get .lib files which I can link statically into my application.
It appears that the documentation on this process is sparse, because it requires non-trivial updates to the build process to get working with Windows CE. The most comprehensive tutorial to this problem appears to be here.
Since you explicitly tagged this boost-asio, I also looked into that component of Boost specifically. Here's a thread from the Boost mailing list that covers this library in detail, including potential failure cases you may experience, JAM file modifications, and a batch file to help you with the build.*
For those reading this: please share your experiences once you get this working. Despite various concerns that Boost is too memory-heavy for embedded applications, Boost provides the ability to use separate packages to meet your needs. I expect other users on SO will be very interested in your experiences getting this working.
* Because people have been expressing problems with the referenced batch file disappearing when Nabble links expire, here's a pastedump for posterity:
#SET VCINSTALLDIR=%VS9INSTALLDIR%\VC
#if "%VS9INSTALLDIR%"=="" goto error_no_VSINSTALLDIR
#if "%VCINSTALLDIR%"=="" goto error_no_VCINSTALLDIR
#echo Setting environment for using Microsoft Visual Studio 2008 tools for WM5.
#set TARGETCPU=X86
#call :GetWindowsSdkDir
#if not "%WindowsSdkDir%" == "" (
set "PATH=%WindowsSdkDir%bin;%PATH%"
)
#rem
#rem Root of Visual Studio IDE installed files.
#rem
#set DevEnvDir=%VS9INSTALLDIR%\Common7\IDE
#set PATH=%VCINSTALLDIR%\CE\bin\x86_arm;%VCINSTALLDIR%\bin;%VS9INSTALLDIR%\Common7\Tools;%DevEnvDir%;%VS9INSTALLDIR%\Common\Tools;%VS9INSTALLDIR%\Common\IDE;%VS9INSTALLDIR%;%PATH%
#set INCLUDE=%STLPORT_PATH%\STLPort-5.2.1\stlport;%VCINSTALLDIR%\ce\include;%CETOOLS%\Windows Mobile 5.0 Pocket PC SDK\include\ARMV4I;%CETOOLS%\Windows Mobile 5.0 Pocket PC SDK\include;%VCINSTALLDIR%\ce\atlmfc\include
#set LIB=%STLPORT_PATH%\STLPort-5.2.1\lib\evc9-arm;%CETOOLS%\Windows Mobile 5.0 Pocket PC SDK\lib\ARMV4I;%VCINSTALLDIR%\ce\ATLMFC\LIB\ARMV4I;%VCINSTALLDIR%\ce\LIB\ARMV4I
#set LIBPATH=
#goto end
:GetWindowsSdkDir
#call :GetWindowsSdkDirHelper HKLM > nul 2>&1
#if errorlevel 1 call :GetWindowsSdkDirHelper HKCU > nul 2>&1
#if errorlevel 1 set WindowsSdkDir=%VCINSTALLDIR%\PlatformSDK\
#exit /B 0
:GetWindowsSdkDirHelper
#for /F "tokens=1,2*" %%i in ('reg query "%1\SOFTWARE\Microsoft\Microsoft SDKs\Windows" /v "CurrentInstallFolder"') DO (
if "%%i"=="CurrentInstallFolder" (
SET "WindowsSdkDir=%%k"
)
)
#if "%WindowsSdkDir%"=="" exit /B 1
#exit /B 0
:error_no_VSINSTALLDIR
#echo ERROR: VS9INSTALLDIR variable is not set.
#goto end
:error_no_VCINSTALLDIR
#echo ERROR: VCINSTALLDIR variable is not set.
#goto end
:end
#SET VCINSTALLDIR=%VS9INSTALLDIR%\VC
#SET FrameworkDir=C:\WINDOWS\Microsoft.NET\Framework
#SET FrameworkVersion=v2.0.50727
#SET Framework35Version=v3.5
#if "%VS9INSTALLDIR%"=="" goto error_no_VSINSTALLDIR
#if "%VCINSTALLDIR%"=="" goto error_no_VCINSTALLDIR
#echo Setting environment for using Microsoft Visual Studio 2008 x86 tools with STLport-5.2.1.
#call :GetWindowsSdkDir
#if not "%WindowsSdkDir%" == "" (
set "PATH=%WindowsSdkDir%bin;%PATH%"
set "INCLUDE=%WindowsSdkDir%include;%INCLUDE%"
set "LIB=%WindowsSdkDir%lib;%LIB%"
)
#rem
#rem Root of Visual Studio IDE installed files.
#rem
#set DevEnvDir=%VS9INSTALLDIR%\Common7\IDE
#set PATH=%DevEnvDir%;%VCINSTALLDIR%\BIN;%VS9INSTALLDIR%\Common7\Tools;%FrameworkDir%\%Framework35Version%;%FrameworkDir%\%FrameworkVersion%;%VCINSTALLDIR%\VCPackages;%PATH%
#set INCLUDE=%STLPORT_PATH%\STLport-5.2.1\stlport;%VCINSTALLDIR%\ATLMFC\INCLUDE;%VCINSTALLDIR%\INCLUDE;%INCLUDE%
#set LIB=%STLPORT_PATH%\STLport-5.2.1\lib\vc9;%VCINSTALLDIR%\ATLMFC\LIB;%VCINSTALLDIR%\LIB;%LIB%
#set LIBPATH=%FrameworkDir%\%Framework35Version%;%FrameworkDir%\%FrameworkVersion%;%VCINSTALLDIR%\ATLMFC\LIB;%VCINSTALLDIR%\LIB;%LIBPATH%
#goto end
:GetWindowsSdkDir
#call :GetWindowsSdkDirHelper HKLM > nul 2>&1
#if errorlevel 1 call :GetWindowsSdkDirHelper HKCU > nul 2>&1
#if errorlevel 1 set WindowsSdkDir=%VCINSTALLDIR%\PlatformSDK\
#exit /B 0
:GetWindowsSdkDirHelper
#for /F "tokens=1,2*" %%i in ('reg query "%1\SOFTWARE\Microsoft\Microsoft SDKs\Windows" /v "CurrentInstallFolder"') DO (
if "%%i"=="CurrentInstallFolder" (
SET "WindowsSdkDir=%%k"
)
)
#if "%WindowsSdkDir%"=="" exit /B 1
#exit /B 0
:error_no_VSINSTALLDIR
#echo ERROR: VSINSTALLDIR variable is not set.
#goto end
:error_no_VCINSTALLDIR
#echo ERROR: VCINSTALLDIR variable is not set.
#goto end
:end
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.