четверг, 18 февраля 2010 г.

Как программно определить, запущены ли мы на 64-разрядной Windows?

Это перевод How to detect programmatically whether you are running on 64-bit Windows. Автор: Реймонд Чен.

Чтобы программно определить, запущены ли вы на 64-разрядной Windows, вы можете использовать функцию IsWow64Process, которая показывает, не запущен ли ваш 32-разрядный процесс в режиме эмуляции.

Но как вы программно определите, не запущен ли ваш 64-битный процесс на 64-битной Windows? Легко.
function Is64BitProcessRunningOn64BitWindows: Boolean;
begin
  Result := True;
end;
Тот факт, что ваша 64-разрядная программа работает, и означает, что вы запущены на 64-разрядной Windows! Если бы вы были на 32-разрядной машине, ваш код не смог бы запуститься.

Это всё равно, что спрашивать: "включен ли компьютер?". Если бы он был выключен, ваша программа не смогла бы задать вопрос.

Конечно же, если вам нужен единый исходный текст для компиляции и в 32-разрядную программу и в 64-разрядную, то вам нужно сделать немного больше работы:
function Is64BitWindows: Boolean;
var
  IsWow64Process: function(hProcess: THandle; out Wow64Process: Bool): Bool; stdcall;
  Wow64Process: Bool;
begin
  {$IF Defined(CPU64)}
  Result := True; // 64-битная программа запускается только на Win64
  {$ELSEIF Defined(CPU16)}
  Result := False; // Win64 не поддерживает 16-разрядные приложения
  {$ELSE}
  // 32-битные программы могут работать и на 32-разрядной и на 64-разрядной Windows
  // так что этот вопрос требует дальнейшего исследования
  IsWow64Process := GetProcAddress(GetModuleHandle(Kernel32), 'IsWow64Process');

  Wow64Process := False;
  if Assigned(IsWow64Process) then
    Wow64Process := IsWow64Process(GetCurrentProcess, Wow64Process) and Wow64Process;

  Result := Wow64Process;
  {$IFEND}
end;
Я добавил ветку для 16-битных программ на случай, если вы достаточно сумасшедший, чтобы писать их сегодня.

Примечание переводчика: поскольку в Delphi пока нет 64-разрядного компилятора, то не известно, как будут называться соответствующие директивы. Поэтому я взял директивы от FreePascal.

12 комментариев:

  1. Огромное спасибо переводчику за труды по переводу статей! Куждый новый перевод жду с нетерпеньем )

    ОтветитьУдалить
  2. Маразм полный, для определения системы и процессора есть соответсвующие функции WinAPI
    SYSTEM_INFO si;
    GetSystemInfo(&si);
    GetNativeSystemInfo(&si);

    Этого вполне достаточно для индентификации всего и вся. Читайте MSDN, а не занимайтесь шаманством с бубнами.

    ОтветитьУдалить
  3. Потрясающий комментарий. Это вы Реймонду Чену говорите MSDN читать, да? :D

    GetNativeSystemInfo - не очень удачное решение, потому что вы не можете предвидеть будущие архитектуры, в то время как IsWow64Process будет работать и сейчас и для любых потенциальных будущих платформ.

    Об использовании IsWow64Process для определения разрядности системы, кстати, сказано в самом описании GetNativeSystemInfo.

    ОтветитьУдалить
  4. Опечатка у вас, должно быть так
    ...
    IsWow64Process := GetProcAddress(GetModuleHandle(Kernel32), 'IsWow64Process');
    ...

    ОтветитьУдалить
  5. Спасибо, исправил.

    P.S. Сайт в подписи можно просто не указывать. Кстати, можно просто выделить ошибочный фрагмент и нажать Ctrl + Enter.

    ОтветитьУдалить
  6. Вышла Delphi XE2 с 64-bit компилятором, директива для x64 следующая {$IFDEF CPUX64}, 32 {$IFDEF CPUX86} для 32-бит кода.

    ОтветитьУдалить
  7. В описании функции IsWow64Process на MSDN указано, что минимальная винда это XP Serice Pack 2. То есть даже на простой XP без сервиспаков она работать не будет.

    Нехорошо.

    ОтветитьУдалить
  8. Microsoft потихоньку удаляет информацию о старых ОС из MSDN. Поэтому, что касается совместимости со старыми системами - надо смотреть в старой документации.

    Далее, 64-битные ОС до Windows Vista стоят крайне особо:
    - 64-битный Windows 2000 был только под Itanium, это не x86, там нет запуска 32-битных приложений.
    - 64-битный Windows XP - это переименованный Windows Server 2003: используется то же ядро и тот же исходный код. Первый выпуск 64-битной XP основан на SP1 для Win2003.
    - Был ещё вариант 64-битного XP для Itanium - это первая редакция Windows с поддержкой WOW64, откуда он перекочевал в 2003 Server и x86-64 XP.

    ОтветитьУдалить
  9. P.S. Именно поэтому у 64-битной XP не было SP1, за RTM шёл SP2.

    ОтветитьУдалить
  10. Иными словами, IsWow64Process есть в любой версии Windows, которая поддерживает запуск 32-битных программ через WOW64 - включая Windows XP Professional x64 Edition RTM (он же - SP1). Это я проверил.

    Разумеется, функцию надо в любом случае импортировать динамически, поскольку в 32-битных системах её нет.

    ОтветитьУдалить
  11. Что за муки?
    Есть миллион способов узнать версию системы и if Pos('64',...)>0 then...

    ОтветитьУдалить
  12. Для 32 процессов из wow64 получаю Tag сервиса. Делаю так:
    [code]
    NtReadVirtualMemory(hp, Pointer(LongWord(TBI.TebBaseAddress)+3936), @Buffer,
    sizeof(Buffer), ReturnLength);
    [/code]
    Магическое смещение нашел на просторах интернета.
    В 64 битном приложении всегда дает 0.
    Как в 64 добыть тег, который указывает на сервис, которому принадлежит поток?

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.

Примечание. Отправлять комментарии могут только участники этого блога.