Определить, является ли текущая версия Windows 32-битной или 64-битной
Вы не поверите, но мой установщик настолько стар, что у него нет возможности определить 64-битную версию Windows.
Есть ли вызов Windows DLL или (что еще лучше) переменная среды, которая предоставит эту информацию для Windows XP и Windows Vista?
Одно возможное решение
Я вижу, что Википедия утверждает, что 64-разрядная версия Windows XP и Windows Vista имеет уникальную переменную среды:, %ProgramW6432%
так что я предполагаю, что она будет пустой в 32-разрядной Windows.
Эта переменная указывает на Program Files
каталог, в котором хранятся все установленные программы Windows и другие. По умолчанию в англоязычных системах установлено C:\Program Files
. В 64-разрядных выпусках Windows (XP, 2003, Vista) также есть, %ProgramFiles(x86)%
какие по умолчанию C:\Program Files (x86)
и %ProgramW6432%
какие по умолчанию C:\Program Files
. Само по %ProgramFiles%
себе зависит от того, является ли процесс, запрашивающий переменную среды, 32-битным или 64-битным (это вызвано перенаправлением 64-битной Windows-on-Windows).
Ответов (23)23
См. Пакетный сценарий, указанный в разделе Как проверить, работает ли на компьютере 32-разрядная или 64-разрядная операционная система» . Он также включает инструкции по проверке этого из реестра:
Вы можете использовать следующую папку реестра, чтобы проверить, работает ли на компьютере 32 или 64-разрядная операционная система Windows:
HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0
На правой панели вы увидите следующие записи реестра:
Identifier REG_SZ x86 Family 6 Model 14 Stepping 12
Platform ID REG_DWORD 0x00000020(32)
Вышеупомянутые символы «x86» и «0x00000020 (32)» указывают на то, что версия операционной системы 32-разрядная.
Из пакетного сценария:
IF PROCESSOR_ARCHITECTURE == x86 AND
PROCESSOR_ARCHITEW6432 NOT DEFINED THEN
// OS is 32bit
ELSE
// OS is 64bit
END IF
Используя Windows API :
if (GetSystemWow64Directory(Directory, MaxDirectory) > 0)
// OS is 64bit
else
// OS is 32bit
Источники:
Я не знаю, какой язык вы используете, но .NET имеет переменную среды, PROCESSOR_ARCHITEW6432
если ОС 64-разрядная.
Если все, что вам нужно знать, - это 32-разрядная или 64-разрядная версия вашего приложения, вы можете проверить IntPtr.Size
. Это будет 4 при работе в 32-битном режиме и 8 при работе в 64-битном режиме.
Я знаю, что это очень давно, но вот что я использую для обнаружения 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
Я хочу добавить сюда то, что использую в сценариях оболочки (но их можно легко использовать на любом языке). Причина в том, что некоторые из решений здесь не работают с WoW64, некоторые используют вещи, которые на самом деле не предназначены для этого (проверка наличия папки * (x86)) или не работают в сценариях cmd. Я считаю, что это «правильный» способ сделать это, и он должен быть безопасным даже в будущих версиях 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
При использовании Windows Powershell, если следующее выражение возвращает истину, значит, это 64-разрядная ОС:
(([Array](Get-WmiObject -Class Win32_Processor | Select-Object AddressWidth))[0].AddressWidth -eq 64)
Это было взято и изменено с: http://depsharee.blogspot.com/2011/06/how-do-detect-operating-system.html (Метод № 3). Я тестировал это на 64-битной Win7 (как в 32-битных, так и в 64-битных сессиях PowerShell) и 32-битной версии XP.
Другой способ, созданный eGerman, который использует PE-номера скомпилированных исполняемых файлов (не полагается на записи реестра или переменные среды):
@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
Во многих ответах упоминаются вызовы IsWoW64Process()
или связанные функции. Это неправильный путь. Вы должны использовать то, GetNativeSystemInfo()
что было разработано для этой цели. Вот пример:
SYSTEM_INFO info;
GetNativeSystemInfo(&info);
if (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
// It's a 64-bit OS
}
См. Также: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724340%28v=vs.85%29.aspx
Ответ для новых версий Windows
Сегодня я опубликовал код по другому вопросу и объяснил, как это сделать с IsWow64Process2 для Windows 10 версии 1511 или более поздней и Windows Server 2016. Кроме того, код определяет, является ли процесс 32-битным или 64-битным и выполняется ли процесс. под эмулятором WOW64.
Одна из основных причин, по которой я опубликовал ответ, заключается в том, что, хотя было несколько предложений использовать IsWow64Process2, ни один код, который я видел, не показал, как это сделать.
См. Ответ здесь: https://answacode.com/a/59377888/1691559
Если вы можете выполнять вызовы API, попробуйте использовать GetProcAddress / GetModuleHandle, чтобы проверить наличие IsWow64Process, который присутствует только в ОС Windows с 64-разрядными версиями.
Вы также можете попробовать переменную среды ProgramFiles (x86), используемую в Vista / 2008 для обратной совместимости, но я не уверен на 100% насчет XP-64 или 2003-64.
Удачи!
В C#:
public bool Is64bit() {
return Marshal.SizeOf(typeof(IntPtr)) == 8;
}
В VB.NET :
Public Function Is64bit() As Boolean
If Marshal.SizeOf(GetType(IntPtr)) = 8 Then Return True
Return False
End Function
Вот код Delphi, чтобы проверить, работает ли ваша программа в 64-битной операционной системе:
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;
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.
Для однострочника VBScript / WMI, который извлекает фактическое количество бит (32 или 64) ОС или оборудования, посмотрите http://csi-windows.com/toolkit/csi-getosbits