Как определить разрядность windows на delphi

Обновлено: 06.07.2024

В настоящее время в связи с распространением 64-разрядных процессоров и операционных систем, перед разработчиками программного обеспечения часто встаёт вопрос о программном определении его разрядности.

Это может быть вызвано как декоративными причинами («автоматически» показывать разрядность пользователю, например, «Моя Программа 1.0 64-разрядная версия») так и необходимостью задействовать в различных архитектурах различные алгоритмы с целью максимально эффективного использования их особенностей и при этом сохранить единую кодовую базу.

Простейшие способы

В Delphi для того чтобы определить разрядность приложения достаточно получить размер не типизированного указателя с помощью стандартного приёма.

В результате будет возвращён размер не типизированного указателя в байтах. Для перевода в биты достаточно умножить полученный результат на 8. В случае 32-разрядного приложения результат будет равен 4 (после умножения 32). В случае же 64-разядного приложения результат будет равен 8 (после умножения 64).

Для C++ существует аналогичный приём.

Конечно, это немного более громоздко, чем в случае Delphi или C++.

Всё эти методы предельно просты и доступны даже для начинающих. Однако все они имеют один общий недостаток. При их использовании в программе компилируются одновременно оба варианта кода (и для 32 и для 64-разрядного приложения). В случае небольших проектов или несущественных отличий в алгоритмах между версиями это может оказаться не критично. В противном случае значительный размер программы будет составлять неиспользуемый код. Это приведёт неоправданному увеличению размеров исполняемого файла программы или файла библиотеки в случае DLL. По этой причине все вышеперечисленные методы для реализации специального кода для конкретной архитектуры по большому счёту не пригодны.

Условная компиляция

К счастью, для этого существует альтернатива в виде директив условной компиляции.

В Delphi имеется стандартный символ условной компиляции WIN32, который обозначает 32-разрядную версию операционной системы Windows. С помощью этого символа и директивы компилятора $IFDEF можно указать, какой код будет компилироваться в случае 32-разрядного приложения, а какой в случае 64-разрядного.

Создание манифеста для программы на Delphi 6 о том что программа поддерживает Windows 10

Начну с того что данный способ определения версий windows для операционных систем выше Windows 8.0 будет корректно работать только при подключении манифеста, а именно например строчкой supportedOS внутри файла манифеста Вы должны явным образом указать какие операционные системы поддерживает Ваша программа. Иначе версия для ОС старше Windows 8.0 будет определяться как Windows 8.0.

Для создания файла манифеста создайте файл с названием и расширением Project1.exe.manifest и разместите в нём следующий текст в UTF-8 кодировке(я написал в названии файла Project1.exe.manifest поскольку моя программа называлась именно так):

Далее создайте файл с названием и расширением manifest.rc и поместите в него следующий текст:

1 24 "Project1.exe.manifest"

После этого в командной строке перейдите в папке где находятся файлы Project1.exe.manifest и manifest.rc(для перехода в папку используется команда cd адрес) и выполните следующий код:

Если команда выполнилась успешно в папке появится файл manifest.res если выполнение произошло с ошибкой, то почитайте какие файлы нужны для выполнения brcc32.exe в этой статье.

Полученный с помощью выполнения указанной выше команды файл manifest.res поместите в папку проекта на Delphi, непосредственно в коде проекта манифест подключается стройкой в implementation в листинге программы, который я приведу в статье ниже данная строчка будет присутствовать.

Файлы для сборки манифеста из примера и получившийся файл .res я разместил в этом архиве, поэтому Вы можете не проделывать все указанные действия а скачать файлы и отредактировать их под себя.

Определение версии Windows в Delphi 6

Определить версию операционной системы Windows в Delphi 6 можно используя Win32Platform, Win32MajorVersion, Win32MinorVersion и Win32BuildNumber. Для примера создадим в Delphi новый проект и на форме разместим Memo1 и Button1 далее заменим весь код проекта на код из листинга:

Для операционной системы Windows 10 Win32MajorVersion будет равен 10, а Win32MinorVersion - 0. Сочетания для других версий операционных систем можно найти в интернет.

Так же версия операционной системы может быть каким то образом определена исходя из менений в Интернет с использованием экземпляра объекта OSVersionInfo, как именно я пока не разбирался.

Функция для Delphi определения является ли Windows 64 битным

Так же иногда может потребоваться узнать является ли Windows на котором запускается программа 64-х разрядным. Для определения можно воспользоваться функцией из листинга ниже, которая возвращает True если программа запущена на 64-х битном Windows. Для использования данной функции подключение выше описанного манифеста не требуется.

Создайте новый проект. Сохраните проект с именем p21.dpr. Основной модуль назовите p21_unit1.pas. В каталоге проекта создайте файл манифеста Windows.manifest. Содержимое файла должно быть следующее:


Далее нам необходимо в каталоге проекта создать файл ресурсов компиляции с именем Windows.rc. Содержимое файла компиляции будет следующее:

1 24 "Windows.manifest"

То есть мы в качестве ресурсов нашего приложения указываем наш файл манифеста.

Файл ресурсов компиляции Windows.rc необходимо скомпилировать при помощи компилятора ресурсов brcc32.exe, этот компилятор ресурсов расположен в каталоге, где расположены бинарные файлы Delphi, у меня это каталог D:\Programs\Delphi7\Files\Delphi7\Bin. Убедитесь, что данный каталог добавлен в переменную окружения Path. Запустите командную строку Windows, перейдите в каталог проекта и выполните команду компиляции ресурсов (Смотрите рисунок 1).

brcc32.exe Windows.rc

В качестве результата в каталоге проекта вы получите файл ресурсов Windows.RES, который необходимо в файле проекта p21.dpr подключить. Смотрите код ниже:


Разместите на форме Form1 текстовую метку Lable1. В метке Label1 мы будем отображать версию операционной системы Windows (Смотрите рисунок 2).


Переходим к написанию кода. Рассмотрим обработчик показа формы Form1, это следующий код:

В обработчике показа формы Form1 мы метке Label1 присваиваем результат возврата функции WinName.

Рассмотрим две функции, которые получают версию операционной системы Windows.


При помощи функции GetVersionEx мы получаем номер основной и второстепенный для нашей операционной системы Windows. Преобразуем основной и второстепенный номер в строку, выполняем соединение этих строк в одну и возвращаем результат выполнения функции WinVerNum.


При помощи функции WinName мы получаем версию операционной системы Windows и возвращаем ее в виде строки.

Думаю каждый хотя бы раз сталкивался с ситуацией, когда на современной ОС не удавалось запустить старую программу, и помогал в этом случае режим совместимости Windows.


В основе работы данного механизма лежит перехват различных функций и эмуляция их поведения, свойственного указанной версии Windows, например, эмулируются ключи реестра, каталоги с документами и прочее. Все это нужно для того, чтобы программа думала, что запущена в выбранной среде.

Если приложение запущено в режиме совместимости, то вызов GetVersionEx вернет фиктивную версию Windows, что, вероятно, не подойдет для системных программ типа твикеров ОС. Как быть в этом случае?

Анализ экспортируемых функций

На просторах сети наткнулся на способ детектирования по наличию/отсутствию экспортируемых функций у системных библиотек. Пример кода:


Решение интересное, но не считаю его приемлемым, так как с выходом каждой версии Windows требуется нетривиальная поддержка.

Используя WMI

Windows Management Instrumentation (WMI) в дословном переводе — это инструментарий управления Windows. Если говорить более развернутo, то WMI — это одна из базовых технологий для централизованного управления и слежения за работой различных частей компьютерной инфраструктуры под управлением платформы Windows.

Из WMI можно получить и версию Windows. Из документации следует что это можно сделать таким запросом:

SELECT Version FROM Win32_OperatingSystem


Запустив WMI Explorer в режиме совместимости с Windows XP, можно увидеть, что это значение не эмулируется:

Метод работает, более того, он полностью документирован, но медленный, и требует тянуть в проект кучу кода по работе с WMI.

Ищем в реестре

Пожалуй самый элегантный и правильный способ найденный в сети — это подсмотреть значение в реестре:
HLKM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion
Ну что же, попробуем:

К сожалению, проверив его на Windows 7 оказалось, что этот ключ реестра эмулируется. Похоже в предыдущих версиях Windows этот способ работал, но, увы — сейчас этот трюк не сработает.

Анализ версии kernel32.dll


Сам не проверял, но говорят, что версия файла у kernel32.dll совпадает с версией Windows. На моем компьютере с Windows 7 это так:

Вполне пригодный способ, но лично мне по непонятным причинам он не нравится, благо есть еще альтернатива.

Анализируем PEB процесса

У каждого Windows-процесса есть структура описывающая его, называется она PEB. Она заполняется при старте процесса и содержит в себе адрес загрузки, список загруженных модулей, параметры командной строки, и, в том числе, версию Windows. Ниже пример модуля, используя который можно получить реальную версию Windows (тестировался на Delphi 2010 Win32):


Скорость работы моментальная, ничего лишнего, единственное НО — недокументированная структура PEB, но как известно Microsoft очень заботится об обратной совместимости, так что с большой долей оптимизма можно считать, что раз описание структуры давно бродит по интернету, то в Microsoft она уже считается документированной.

Читайте также: