Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Определить версию Windows


Автор: rudolfninja 12.8.2015, 18:35
Приветсвую всех.
Столкнулся с такой проблемой, надо определить версию ОС, не используя GetVersionEx. Дело в том, что на msdn по поводу этой функции написано:
Цитата

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.

А мне как раз надо, чтоб мое приложение определяло, что оно работает на Windows 10. 
Вариант добавить в манифест приложения Windows 10 не подходит.

Вот, собственно и вопрос: есть ли какие способы определить версию винды используя только user-mode функции (RtlGetVersion не подходит, т.к. она выполняется в kernel-моде).

Спасибо.

Автор: Alexeis 12.8.2015, 19:35
Ну собственно там же и написано что нужно делать https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972(v=vs.85).aspx

Автор: feodorv 12.8.2015, 21:37
MicroSoft дурит, конечно.

Цитата(rudolfninja @  12.8.2015,  18:35 Найти цитируемый пост)
Вариант добавить в манифест приложения Windows 10 не подходит.

Почему? Вот https://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx обещано:
Цитата
Adding the trustInfo isn’t essential, but it is highly recommended. This will allow your .exe to always get the correct version, no matter whether the operating system is Windows 8.1 or Windows 8.
Верить или нет - не знаю, особенно по отношению к Windows 10, но trustInfo, вроде, не есть "добавить в манифест приложения Windows 10".


Цитата(rudolfninja @  12.8.2015,  18:35 Найти цитируемый пост)
RtlGetVersion не подходит, т.к. она выполняется в kernel-моде

Народ вызывает и в user-mode... Но, http://www.codeproject.com/Articles/678606/Part-Overcoming-Windows-s-deprecation-of-GetVe?msg=5080848#xx5080848xx, и она врёт:
Цитата
No matter if you use GetVersionEx() or RtlGetVersion(). Both will return the WRONG OS version if the user has right clicked your EXE and in 'Properties' -> 'Compatibility Mode' has chosen an older operating system.
В общем, по ссылке много неочевидного кода, но я так и не понял, решена проблема или нет.


Alexeis, спасибо за ссылку.

Автор: rudolfninja 12.8.2015, 23:41
Alexeis, ваш вариант не подходит, потому что предполагается, что программа будет использоваться и компилироваться под Windows XP (build server у нас на WinXP еще), а там нет нужного API.

Цитата(feodorv @  12.8.2015,  21:37 Найти цитируемый пост)
Цитата(rudolfninja @  12.8.2015,  18:35 )
Вариант добавить в манифест приложения Windows 10 не подходит.

Почему? Вот здесь обещано:


Ситуация такова, что я пишу .dll, которая потом тянется из java-кода. Нынешняя версия java не понимает Windows10 и поэтому моя dll определяет ее как Windows 8. Поэтому мне надо как-то самому определить, что я работаю под Windows 10

Автор: Guinness 13.8.2015, 07:43
Цитата(rudolfninja @  13.8.2015,  00:41 Найти цитируемый пост)
Alexeis, ваш вариант не подходит, потому что предполагается, что программа будет использоваться и компилироваться под Windows XP (build server у нас на WinXP еще), а там нет нужного API.

Имелось в виду, что нужно компилировать под 10ку? Ну, можно же вызывать функцию динамически, т.е. подгружать её на этапе исполнения с помощью LoadLibrary и GetProcAddress. Соответственно, предварительно проверив версию dll.

Автор: rudolfninja 13.8.2015, 08:37
Цитата(Guinness @  13.8.2015,  07:43 Найти цитируемый пост)
Имелось в виду, что нужно компилировать под 10ку?

Ну да.
Вот кстати, с версией dll, может просто попробовать определять версию dll, и если она такая же как на 10, то считать, что текущая ОС - Windows 10?

Автор: Alexeis 13.8.2015, 10:05
Цитата(Guinness @  13.8.2015,  08:43 Найти цитируемый пост)
 Ну, можно же вызывать функцию динамически, т.е. подгружать её на этапе исполнения с помощью LoadLibrary и GetProcAddress. Соответственно, предварительно проверив версию dll. 

  Если функция IsWinows10 умеет возвращать false то очевидно, что она реализована не в библиотеке, а в SDK. С новым SDK под windows XP не сомпилишься, так что rudolfninja прав. В его ситуации не проканает.

Автор: rudolfninja 13.8.2015, 10:24
Я вот что обнаружил, у kernel32.dll версия библиотеки в Windows 10 - 10.0.10240.16384, а в Windows 7, например, 6.1.7601.18847. Получается, что первые три разряда (числа), это majorVersion, minorVersion и buildNumber самой операционной системы. То есть, я могу получить версию библиотеки и проверить по ней.
Есть какие-нибудь предположения, чем плох этот вариант?

Автор: volatile 13.8.2015, 11:13
Цитата(rudolfninja @  13.8.2015,  10:24 Найти цитируемый пост)
Есть какие-нибудь предположения, чем плох этот вариант? 

недокументированность
нет гарантии что это будет работать на всех разновидностях системы.
и что будет с будущими системами, тем более не ясно

Можно попробовать заюзать VerifyVersionInfo, VerSetConditionMask
Работают начиная с win 2000
пример использования
http://www.codeproject.com/Articles/678606/Part1-Overcoming-Windows-8-1s-deprecation-of-GetVe
там есть и еще варианты

Автор: rudolfninja 13.8.2015, 11:23
Цитата(volatile @  13.8.2015,  11:13 Найти цитируемый пост)
Можно попробовать заюзать VerifyVersionInfo, VerSetConditionMask

Пробовал такой вариант, на Windows 10 дает отрицательный результат. Я ставил маску, чтоб dwMajorVersion был выше или равен 10, но все равно не срабатывает. Видимо, там внутри вызывается GetVersionEx, который возвращает, что текущая версия - Windows 8

Автор: Alexeis 13.8.2015, 11:32
Я проверил, versionhelpers.h, там реализация функций прям инлайн. Файлик приатачил к посту. С точки зрения ОС используется функция VerifyVersionInfoW, которая появилась в Windows 2000. Думаю можно использовать этот файлик с любым SDK.

Автор: rudolfninja 13.8.2015, 12:22
Вот такой код на Windows 10 вернул false:
Код

OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, { 0 }, 0, 0 };
DWORDLONG        const dwlConditionMask = VerSetConditionMask(VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL),VER_MINORVERSION, VER_GREATER_EQUAL);

osvi.dwMajorVersion = 10;
osvi.dwMinorVersion = 0;

std::cout << (VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask) != FALSE) << std::endl;

Автор: rudolfninja 13.8.2015, 12:58
Мне кажется, проблема в VerifyVersionInfoW, которая внутри себя вызывает GetVersionEx

Автор: Alexeis 13.8.2015, 13:13
Цитата(http://codeverge.com/embarcadero.delphi.general/windows-10-and-existing-vcl-applic/2031072)

Done a little searching, this blog confirms that VerifyVersionInfo is deliberately broken for Windows 10, so older applications without a new manifest can not detect Windows 10. Angus http://blogs.msdn.com/b/chuckw/archive/2013/09/10/manifest-madness.aspx Windows 10 Note that the latest version of Windows includes the default version lie shim that was present in Windows 8.1. If you have the 8.1 GUID present in the <compatibility> section of the manifest, Windows 10 will report version 6.3 if your application uses the legacy GetVersion(Ex) APIs. Without it or with only older GUIDs, it will report 6.2. To get the version number reported as 10.0 (note this was 6.4 with the original Windows 10 Technical Preview build 9841), you must add another GUID to your manifest: <!-- Windows 10 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> Update: With Windows 10 VerifyVersionInfo is now subject to the same manifest-based behavior as GetVersion(Ex): by default IsWindows8OrGreater and earlier will return 'true' as expected on Windows 10, but both IsWindows8Point1OrGreater and IsWindows10OrGreater will return 'false' 
without the appropriate GUIDs present in the <compatibility> section
. - See more at: http://codeverge.com/embarcadero.delphi.general/windows-10-and-existing-vcl-applic/2031072#sthash.rdaLfJ48.dpuf


Добавлено через 45 секунд
Чтоб функция работала похоже нужно манифест включить в экзешник

Автор: rudolfninja 13.8.2015, 18:13
Решил проблему с помощью WMI. Получил из WMI строку с версией ОС и распарсил ее на нужные части.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)