- GetVersion function (sysinfoapi.h)
- Syntax
- Parameters
- Return value
- Remarks
- Examples
- GetVersionExW function (sysinfoapi.h)
- Syntax
- Parameters
- Return value
- Remarks
- Examples
- Windows api функции getversionex
- Содержание
- Структура API ОС
- API для получения версии в Windows
- API для получения версии в Linux
- API для получения версии в MacOSX
- Кодировка строк в API ОС
GetVersion function (sysinfoapi.h)
GetVersion may be altered or unavailable for releases after WindowsВ 8.1. Instead, use the Version Helper functions. For Windows 10 apps, please see Targeting your applications for Windows.
With the release of WindowsВ 8.1, the behavior of the GetVersion API has changed in the value it will return for the operating system version. The value returned by the GetVersion function now depends on how the application is manifested.
Applications not manifested for WindowsВ 8.1 or WindowsВ 10 will return the WindowsВ 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersion will always return the version that the application is manifested for in future releases. To manifest your applications for WindowsВ 8.1 or WindowsВ 10, refer to Targeting your application for Windows.
Syntax
Parameters
This function has no parameters.
Return value
If the function succeeds, the return value includes the major and minor version numbers of the operating system in the low-order word, and information about the operating system platform in the high-order word.
For all platforms, the low-order word contains the version number of the operating system. The low-order byte of this word specifies the major version number, in hexadecimal notation. The high-order byte specifies the minor version (revision) number, in hexadecimal notation. The high-order bit is zero, the next 7 bits represent the build number, and the low-order byte is 5.
Remarks
The GetVersionEx function was developed because many existing applications err when examining the packed DWORD value returned by GetVersion, transposing the major and minor version numbers. GetVersionEx forces applications to explicitly examine each element of version information. VerifyVersionInfo eliminates further potential for error by comparing the required system version with the current system version for you.
Examples
The following code fragment illustrates how to extract information from the GetVersion return value: OSVERSIONINFOEX
GetVersionExW function (sysinfoapi.h)
[GetVersionEx may be altered or unavailable for releases after WindowsВ 8.1. Instead, use the Version Helper functions]
With the release of WindowsВ 8.1, the behavior of the GetVersionEx API has changed in the value it will return for the operating system version. The value returned by the GetVersionEx function now depends on how the application is manifested.
Applications not manifested for WindowsВ 8.1 or WindowsВ 10 will return the WindowsВ 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases. To manifest your applications for WindowsВ 8.1 or WindowsВ 10, refer to Targeting your application for Windows.
Syntax
Parameters
An OSVERSIONINFO or OSVERSIONINFOEX structure that receives the operating system information.
Before calling the GetVersionEx function, set the dwOSVersionInfoSize member of the structure as appropriate to indicate which data structure is being passed to this function.
Return value
If the function succeeds, the return value is a nonzero value.
If the function fails, the return value is zero. To get extended error information, call GetLastError. The function fails if you specify an invalid value for the dwOSVersionInfoSize member of the OSVERSIONINFO or OSVERSIONINFOEX structure.
Remarks
Identifying the current operating system is usually not the best way to determine whether a particular operating system feature is present. This is because the operating system may have had new features added in a redistributable DLL. Rather than using GetVersionEx to determine the operating system platform or version number, test for the presence of the feature itself. For more information, see Operating System Version.
The GetSystemMetrics function provides additional information about the current operating system.
Product | Setting |
---|---|
Windows XP Media Center Edition | SM_MEDIACENTER |
WindowsВ XP Starter Edition | SM_STARTER |
Windows XP Tablet PC Edition | SM_TABLETPC |
Windows ServerВ 2003В R2 | SM_SERVERR2 |
В
To check for specific operating systems or operating system features, use the IsOS function. The GetProductInfo function retrieves the product type.
To retrieve information for the operating system on a remote computer, use the NetWkstaGetInfo function, the Win32_OperatingSystem WMI class, or the OperatingSystem property of the IADsComputer interface.
To compare the current system version to a required version, use the VerifyVersionInfo function instead of using GetVersionEx to perform the comparison yourself.
If compatibility mode is in effect, the GetVersionEx function reports the operating system as it identifies itself, which may not be the operating system that is installed. For example, if compatibility mode is in effect, GetVersionEx reports the operating system that is selected for application compatibility.
Examples
When using the GetVersionEx function to determine whether your application is running on a particular version of the operating system, check for version numbers that are greater than or equal to the desired version numbers. This ensures that the test succeeds for later versions of the operating system. For example, if your application requires Windows XP or later, use the following test.
For an example that identifies the current operating system, see Getting the System Version.
The sysinfoapi.h header defines GetVersionEx as an alias which automatically selects the ANSI or Unicode version of this function based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for Function Prototypes.
Windows api функции getversionex
Статья показывает способы работы с API операционных систем на примере определения версии системы.
Содержание
Каждая операционная система имеет свой способ версионирования. Очевидно, что способ определения версии системы завязан на особенности конкретной ОС. Мы рассмотрим способы определения версии на Windows, Linux и Mac OS X.
Попутно мы освоим более важную вещь: работу с API операционных систем. API — это сокращение от Application Programming Interface. Каждая ОС предоставляет программисту низкоуровневые библиотеки, формирующие цельный интерфейс, позволяющий приложению реагировать на события ОС, либо делегировать ей свои задачи, а также общаться с другими процессами. Этот интерфейс и называется API операционной системы.
Структура API ОС
По историческим причинам большинство API ОС предоставляет средства в процедурном стиле и на языке C89. Такие API состоят из функций, макросов-констант и структур, представляющих объекты системы.
API ОС принято оставлять неизменными на протяжении десятилетий, чтобы даже скомпилированные программы продолжали работать, и не нужно было править исходники или перекомпилировать их заново. Расплата за это — неудобный, построенный по старым стандартам интерфейс. Но эта проблема легко решается с помощью написания фасадов, предоставляющих более удобный и высокоуровневый интерфейс. Готовые фасады есть во многих программных библиотеках.
Обычно функции в составе API ОС реализованы в динамических библиотеках, то есть их адреса и реализации становятся известны только после запуска программы, что и позволяет использовать новые версии ОС без перекомпиляции предназначенных для неё программ.
Кроме функций API есть также вызовы ядра ОС, которые работают с помощью системных прерываний (т.е. требуют помощи процессора), а не на основе стека и прыжка по адресу функции. Вызов ядра — дорогая операция, потому что в процессе вызова процессор переходит из защищённого режима (userspace mode) в режим прямой работы с памятью и устройствами (kernel mode), а затем возвращается обратно в защищённый режим.
Вызовы ядра — это единственный способ попросить систему об операции, выходящей за полномочия процесса программы, например, о создании нового процесса. Есть разница в отношении к системным вызовам в мире UNIX и в мире Windows
- В UNIX-системах вызовы ядра доступны программисту напрямую, и считается нормальным их использовать
- В Windows вызовы ядра обычно начинаются с префикса “Rtl”, и не рекомендуются для использования программистом. Для любой функции с префиксом “Rtl” есть замена в составе WinAPI (обычно это функция с тем же именем за вычетом префикса “Rtl”).
Функции API ОС и вызовы ядра вместе называют вызовами API ОС. Эти вызовы лежат в основе множества операций по работе с файлами, устройствами и сетью, но стоят дороже обычного вызова функции в собственном коде программы.
API для получения версии в Windows
Версия Windows отображается в модуле настройки, доступном из панели управления:
Узнать версию ОС программно Windows можно с помощью WinAPI. WinAPI расшифровывается как Windows API. Он детально задокументирован на сайте msdn.microsoft.com — портале от компании Microsoft, предназначенном для сторонних разработчиков. Найти документацию по функциям WinAPI можно, передав в поисковик запрос “msdn FunctionName” или “FunctionName site:msdn.microsoft.com”. Также помогают запросы из разряда “winapi how to …”.
Большая часть WinAPI доступна при подключении единственного заголовочного файла Windows.h . А это — небольшой пример:
Имейте ввиду, что функция GetVersion возвращает кодовый номер версии, который нужно сопоставить с таблицей версий и определить человекопонятное имя.
В WinAPI действует ряд соглашений в именовании:
- функции именуются в UpperCamelCase, например, GetVersion, GetVersionEx. Сокращения используются в редких случаях, например, суффиксом “Ex” помечают расширенную версию более старой фукнции.
- имена типов данных именуются в верхнем регистре, часто с сокращениями: RECT, POINT, HMENU (handle to menu), OSVERSIONINFO (OS version information) и так далее
- для создания и удаления системных объектов, например, типа XYZ, предоставляются функции с именами вида “CreateXYZ” и “DestroyXYZ”
- многие привычные типы данных получили свои синонимы (в целях максимального контроля над стабильностью)
- WORD — машинное слово, 16-битное целое без знака, аналог uint16_t
- DWORD — удвоенное машинное слово, 32-битное целое без знака, аналог uint32_t
- BOOL — синоним типа int, введённый по той причине, что в языке C89 нет типа bool. Тип bool появился в C++, а тип _Bool — в C99
- LPCSTR — синоним const char * , расшифровывается как Left-Pointer to Const String, т.е. изменяемый (способный стоять в левой части присваивания) указатель на неизменяемую строку в стиле C, завершённую нулевым символом.
- LPSTR — синоним char * , расшифровывается как Left-Pointer to String, т.е. изменяемый (способный стоять в левой части присваивания) указатель на изменяемую строку в стиле C, завершённую нулевым символом.
- LPCWSTR — синоним const wchar_t * , расшифровывается как Left-Pointer Wide Const String, т.е. вместо типа char использует тип wide char, способный представлять символы одной из кодировок Unicode — UTF16
Вы могли заметить, что в предыдущих двух примерах используются устаревшие функции. Начиная с Windows 8, компания Microsoft решила объявить устаревшими GetVersion и GetVersionEx, и они теперь могут возвращать неправильное значение согласно спецификации.
Вместо них предлагается использовать функции из заголовка VersionHelpers.h. Эти функции не реализованы в библиотеках WinAPI и всего лишь дают фасад для вызова VerifyVersionInfo. Функции из состава VersionHelpers.h имеют более привычное именование версий ОС в сравнении с GetVersion и GetVersionEx.
API для получения версии в Linux
Мы будем рассматривать получение версии на примере Ubuntu, т.к. этот дистрибутив использует подавляющая часть пользователей GNU/Linux. Через графический интерфейс информацию о системе можно узнать в панели настроек:
Для API в GNU/Linux характерна разобщённость: разные разработчики создают различные библиотеки, подходы к организации API этих библиотек и уровень квалификации их авторов может сильно варьироваться. Есть некоторые островки стабильности среди этого хаоса:
- стандарт POSIX, который расширяет стандартную библиотеку C89 новыми функциями, и переносим на любую UNIX-подобную систему, в том числе на MacOSX и даже частично на Windows; в Linux большая часть POSIX доступна из заголовка unistd.h
- системные вызовы ядра Linux, которые остаются стабильными на протяжении десятилетий, и доступны из заголовков в каталоге sys/
- особенно популярные, распространнённые в разных дистрибутивах и проверенные библиотеки, интерфейс которых тщательно спроектирован и не меняется на протяжении многих лет
- примеры таких библиотек: Qt, GTK, SDL2
Для систематизации документации в Linux придумано несколько разных решений. В первую очередь рассмотрим команду man (от слова “manual”). Команда man — это команда UNIX-систем, отображающая форматированную документацию в собственном формате man, набор которой зависит от установленных в системе пакетов. Вот такой вывод даёт команда “man printf”:
Нетрудно понять, что это документация не о функции “printf” стандартной библиотеки C89, а об утилите командной строки с тем же названием. Дело в том, что справка man распределена по разделам:
- раздел 1 содержит документацию по утилитам командной строки, и к нему можно обраться командой “man 1 printf”
- раздел 2 содержит документацию по интерфейсам и системным вызовам ядра Linux, и команда “man 2 printf” не даст результата:
- раздел 3 содержит документацию по функциям языка C, входящим в стандартную библиотеку, в стандарт POSIX и в прикладные библиотеки. Обраться к этой документации можно командой “man 3 printf”
- есть и другие разделы, но они не представляют интереса для наших задач
Документация из разделов man есть не только на Linux-машинах, но и в интернете, например на сайте opennet.ru. Получить эту документацию можно, используя запрос вида “man printf” в поисковике.
Для получения версии ядра Linux существует системный вызов uname, информация о котором есть в разделе 2 справки man.
Из документации понятно поведение функции, и указано, что функция находится в заголовке “sys/utsname.h”. Можно написать функцию, которая будет получать и печатать информацию о версии ядра:
Результат вызова функции приведён ниже. Из него понятно, что поле nodename содержит имя компьютера в сети, а поля sysname и release — версию ядра операционной системы. Поля domainname, machine и version не несут особенно важной информации, и появления имени дистрибутива Ubuntu в поле version является особенностью сборки, а не общей закономерностью.
Для определения имени и номера версии дистрибутивы могут быть доступны разные приёмы:
- современные дистрибутивы предоставляют утилиту командной строки “lsb_release”, выводящую версию дистрибутива, и эта утилита может быть вызвана программно с помощью “popen”; полный вывод доступен при запуске с параметром “lsb_release -a”, а справочную информацию можно узнать при запуске с параметром “lsb_release -h”
- та же информация обычно доступна в текстовом файле “/etc/lsb-release”, и вы можете вывести его в консоль командой “cat /etc/lsb-release”
- файл “/etc/os-release” может отсутствовать или иметь разный формат в некоторых дистрибутивах, в Ubuntu 16.04 он выглядит так:
Реализация чтения файла или запуска lsb_release командой popen останется за пределами статьи.
API для получения версии в MacOSX
В MacOSX доступен тот же самый API POSIX, включающий в себя и вызов uname. Кроме POSIX также доступны
- системные вызовы ядра Darwin
- библиотека Carbon языка C89, которая в последних версиях OSX считается устаревшей
- библиотеки (фреймворки) языка Objective-C, которые могут быть использованы совместно с кодом на языке C89
- для смешивания Objective-C и C в одном файле используются файлы с расширением “.m”, к которым можно подключать заголовки “.h”
- для смешивания Objective-C и C++ в одном файле используются файлы с расширением “.mm”, к которым также можно подключать заголовки “.h”
Ранний способ определения версии OSX — функция “Gestalt” из файла “CarbonCore/OSUtils.h”. К сожалению, эта функция объявлена устаревшей в MacOSX 10.8.
Один из эвристических способов определения версии OSX связан с определением версии ядра Darwin, и последующей выборке по таблице:
Для определения версии ядра можно использовать многофункциональный системный вызов sysctl:
Кодировка строк в API ОС
В современных UNIX-подобных системах для работы со строками используется кодировка UTF-8, которая является мультибайтовой. Это означет, что в UTF8 базовой единицей является тип “char” размером в 1 байт, но один символ Unicode представляется либо одним, либо несколькими байтами. Для правильного разделения строки UTF8 на символы следует сканировать строку последовательно из начала в конец:
- все ASCII-символы с кодами от 0 до 127 представляются одним байтом так же, как в ASCII, поэтому любой текст в кодировке ASCII является и текстом в кодировке UTF-8, например, большинство английских текстов соответствуют требованиям UTF-8
- для остальных символов значение первого байта находится вне диапазона ASCII
В Windows в процессе перехода на кодировку Unicode было принято иное решение: используется базовый тип “wchar_t” (размер которого на Windows равен 2 байтам, а на UNIX-платформах — 4-м), и символы кодируются в UTF-16. Вопреки частому заблуждению, кодировка UTF-16 точно так же является мультибайтовой: базовой единицей является тип “wchar_t” с размером 2 байта на Windows, но один символ Unicode представляется либо одним, либо несколькими “wchar_t”.
На UNIX-подобных ОС тип “wchar_t” и соответствующие ему типы “std::wstring”, “std::wostream”, функции “std::to_wstring”, глобальные переменные “std::wcout” работают в кодировке UCS32, в которой символы представляются четырьмя байтами.
Из-за очевидного перерасхода памяти wide-строки, основанные на wchar_t, непопулярны в системном программировании для UNIX, но крайне популярны на Windows, где wide-строки более компактны. Кроме того, именно с UTF-16 работает ядро Windows и современные вызовы WinAPI.
Современный C++ имеет средства для конвертации между “std::string” в UTF8 и “std::wstring” прямо в стандартной библиотеке:
Ещё несколько нюансов Wide Strings, которые следует знать:
- литералы для Wide String записываются так: L»Wide String Value»
- в Windows для для каждой функции и структуры WinAPI, работающей со строками, есть две версии: одна с суффиксом “A”, другая с суффисом “W”
- версия с суффиксом A работает в текущей кодировке ANSI-кодировке, которая обынчо является однобайтовой и не может представить символы алфавита, отличного от языка системы, например, Windows с английской локалью сломает кодировку кириллических строк при использовании ANSI-версий функций
- версия с суффиксом W работает в кодировке UTF16 и принимает указатели на “wchar_t” строки вместо указателей на “char”-строки, только такие функции обеспечивают простую и корректную работу в мультиязычной системе
- версия функции WinAPI без суффикса обычно прсто является макросом, указывающим либо на ANSI-версию, либо на UTF16-версию в зависимости от настроек компиляции. В Visual Studio управление данным поведением возможно через свойство “Unicode” в основных настройках проекта.