определить, является ли текущая версия windows 32-битной или 64-битной

<p>верьте или нет, мой установщик настолько стар, что у него нет возможности обнаружить 64-разрядную версию windows.</p><p>есть ли в windows dll вызов или (что еще лучше) переменная среды, которая предоставит эту информацию для windows xp и windows vista?</p><p><strong>одно из возможных решений</strong></p><p>я вижу, что в википедии говорится, что 64-разрядная версия windows xp и windows vista имеет уникальную переменную среды: <code>%programw6432%</code>, поэтому я предполагаю, что она будет пустой в 32-разрядной windows.</p><p>эта переменная указывает на каталог <code>program files</code>, в котором хранятся все установленные программы windows и другие. по умолчанию в англоязычных системах используется <code>c:\program files</code>. в 64-разрядных выпусках windows (xp, 2003, vista) также есть <code>%programfiles(x86)%</code>, по умолчанию <code>c:\program files (x86)</code> и <code>%programw6432%</code>, по умолчанию <code>c:\program files</code>. сам <code>%programfiles%</code> зависит от того, является ли процесс, запрашивающий переменную среды, самим 32-разрядным или 64-разрядным (это вызвано 64-разрядным перенаправлением windows-on-windows).</p>

<p>см. пакетный сценарий, указанный в <em> <a href="http://support.microsoft.com/kb/556009/en-us">как проверить, работает ли компьютер на 32-битной или 64-битной операционной системе</a> </em>. он также включает инструкции для проверки этого из реестра:</p><p>вы можете использовать следующее расположение реестра, чтобы проверить, работает ли компьютер под управлением 32- или 64-разрядной операционной системы windows:</p><pre><code>hklm\hardware\description\system\centralprocessor\0 </code></pre><p>в правой панели вы увидите следующие записи реестра:</p><pre><code>identifier reg\_sz x86 family 6 model 14 stepping 12 platform id reg\_dword 0x00000020(32) </code></pre><p>вышеупомянутые "x86" и "0x00000020 (32)" указывают, что версия операционной системы является 32-разрядной.</p>

<p>чтобы проверить наличие 64-разрядной версии windows в командной строке, я использую следующий шаблон:</p><p>test.bat:</p><pre><code>@echo off if defined programfiles(x86) ( @echo yes @echo some 64-bit work ) else ( @echo no @echo some 32-bit work ) </code></pre><p><code>programfiles(x86)</code> - это переменная среды, автоматически определяемая cmd.exe (как 32-разрядная, так и 64-разрядная версии) только на 64-разрядных компьютерах windows.</p>

<p>вот некоторый код delphi, чтобы проверить, работает ли ваша программа в 64-битной операционной системе:</p><pre class="lang-default prettyprint-override"><code>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; </code></pre>

<p>я проверил решение, которое я предложил в своем вопросе:</p><p>протестировано для переменной среды windows: programw6432</p><p>если он не пустой, то это 64-битная windows.w</p>

<p>из пакетного скрипта:</p><pre><code>if processor\_architecture == x86 and processor\_architew6432 not defined then // os is 32bit else // os is 64bit end if </code></pre><p>использование windows <a href="http://en.wikipedia.org/wiki/application\_programming\_interface">api</a> :</p><pre><code>if (getsystemwow64directory(directory, maxdirectory) > 0) // os is 64bit else // os is 32bit </code></pre><p>источники:</p><ol> <li><em> <a href="http://blogs.msdn.com/b/david.wang/archive/2006/03/26/howto-detect-process-bitness.aspx">howto: определить разрядность процесса</a> </em></li> <li><em> <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724405%28v=vs.85%29.aspx">функция getsystemwow64directory</a> </em></li> </ol>

<p>если вы можете выполнять вызовы api, попробуйте использовать <a href="http://msdn2.microsoft.com/en-us/library/ms683212.aspx">getprocaddress</a> / <a href="http://msdn2.microsoft.com/en-us/library/ms683199.aspx">getmodulehandle</a> , чтобы проверить наличие <a href="http://msdn2.microsoft.com/en-us/library/ms684139.aspx">iswow64process</a> , который присутствует только в ос windows с 64 версии.</p><p>вы также можете попробовать <strong> переменную среды programfiles (x86) </strong>, используемую в vista/2008 для обратной совместимости, но я не уверен на 100% в xp-64 или 2003-64.</p><p>удачи!</p>

<p>я использовал это в сценарии входа в систему для обнаружения 64-битной windows</p><p>if "% programw6432%" == "% programfiles%" перейти к is64flag</p>

<p>я не знаю, какой язык вы используете, но <a href="http://en.wikipedia.org/wiki/.net\_framework">. net</a> имеет переменную окружения <code>processor\_architew6432</code>, если ос 64-битная.</p><p>если вам нужно знать, работает ли ваше приложение 32-битным или 64-битным, вы можете проверить <code>intptr.size</code>. это будет 4, если работает в 32-битном режиме и 8, если работает в 64-битном режиме.</p>

<p>для однострочного vbscript/wmi, который извлекает фактическое число бит (32 или 64) ос или аппаратного обеспечения, взгляните на <a href="http://csi-windows.com/toolkit/csi-getosbits">http://csi-windows.com/toolkit/csi-getosbits</a> </p>

<p>я хочу добавить то, что я использую в сценариях shell (но может легко использоваться на любом языке) здесь. причина в том, что некоторые решения здесь не работают с wow64, некоторые используют вещи, которые на самом деле не предназначены для этого (проверка наличия папки * (x86)), или не работают в сценариях cmd. я считаю, что это "правильный" способ сделать это и должен быть безопасным даже в будущих версиях windows.</p><pre><code> @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 </code></pre>

<p>во многих ответах упоминается вызов <code>iswow64process()</code> или связанных функций. это не <em> правильный </em> способ. вы должны использовать <code>getnativesysteminfo()</code>, которая была разработана для этой цели. вот пример:</p><pre><code>system\_info info; getnativesysteminfo(&info); if (info.wprocessorarchitecture == processor\_architecture\_amd64) { // it's a 64-bit os } </code></pre><p>также см .: <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms724340%28v=vs.85%29.aspx">https://msdn.microsoft.com/en-us/library/windows/desktop/ms724340%28v=vs.85%29.aspx</a> </p>

<p>я не знаю, в какой версии windows она существует, но в windows vista и более поздних версиях она работает:</p><pre><code>function is64bit as boolean dim x64 as boolean = system.environment.is64bitoperatingsystem if x64 then return true else return false end if end function </code></pre>

<p>в c #:</p><pre><code>public bool is64bit() { return marshal.sizeof(typeof(intptr)) == 8; } </code></pre><p>в <a href="http://en.wikipedia.org/wiki/visual\_basic\_.net">vb.net</a> :</p><pre><code>public function is64bit() as boolean if marshal.sizeof(gettype(intptr)) = 8 then return true return false end function </code></pre>

<p>я использую это:</p><pre><code>@echo off if "%processor\_architecture%"=="amd64" ( echo 64 bit ) else ( echo 32 bit ) </code></pre><p>он работает в windows xp, тестировал его в windows xp professional. и 64-битная, и 32-битная.</p>

<p>конечно, лучший способ - просто проверить наличие двух каталогов программных файлов: "program files" и "program files (x86)". преимущество этого метода в том, что вы можете делать это, когда операционная система не работает, например, если машина не запустилась, и вы хотите переустановить операционную систему</p>

<p>я протестировал следующий пакетный файл в windows 7 x64/x86 и windows xp x86, и это нормально, но я еще не пробовал windows xp x64, но это, вероятно, будет работать:</p><pre><code>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) </code></pre>

<p>вот более простой метод для пакетных скриптов</p><pre><code> @echo off goto %processor\_architecture% :amd64 echo amd64 goto :eof :x86 echo x86 goto :eof </code></pre>

<p>я знаю, что это древний, но вот что я использую для обнаружения win764</p><pre><code>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 </code></pre>

<p>используя windows powershell, если следующее выражение возвращает true, тогда это 64-битная ос:</p><p><code>(([array](get-wmiobject -class win32\_processor | select-object addresswidth))[0].addresswidth -eq 64)</code></p><p>это было взято и изменено из: <a href="http://depsharee.blogspot.com/2011/06/how-do-detect-operating-system.html">http://depsharee.blogspot.com/2011/06/how-do-detect-operating-system.html</a> (метод № 3). я проверил это на 64-битной win7 (как в 32-, так и в 64-битной сессиях powershell) и xp 32-битной.</p>

<p>интересно, если я использую</p><pre><code>get-wmiobject -class win32\_environment -filter "name='processor\_architecture'" </code></pre><p>я получаю amd64 как в 32-битной, так и в 64-битной ise (на win7 64-битной).</p>

<p>другой способ <a href="http://www.dostips.com/forum/viewtopic.php?f=3&t=5826">созданный egerman</a> , который использует числа pe скомпилированных исполняемых файлов (не полагается на записи реестра или переменные среды):</p><pre><code>@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 </code></pre>