Visual Studio устанавливает WINVER / _WIN32_WINNT для Windows 8 в Windows 7?

Я провожу некоторое тестирование на Windows 7 x64 с использованием Visual Studio 2012. Похоже, что Microsoft Toolchain настраивает_WIN32_WINNT в0x602 (_WIN32_WINNT_WIN8). Результаты нашей тестовой программы вThe procedure entry point GetOverlappedResultEx could not be located in the dynamic link library KERNEL32.dll:

У меня два вопроса. Во-первых, из болезненного любопытства, почему настройки Microsoft_WIN32_WINNT к значению, которое не подходит для среды выполнения? Я могу понять, если пользователь хочет сделать это, но не Microsoft, так как это ломает вещи (г.о.).

Во-вторых, как мы устанавливаемWINVER или же_WIN32_WINNT к символической "Эта платформа"? В данном случае «эта платформа» - Windows 7. Когда я тестирую на Windows Vista, это будет другая платформа. Когда я тестирую на Windows 8, это будет другая платформа. И когда я тестирую под приглашением разработчика ARM для Windows Phone и Windows Store, это будет еще одна платформа.

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

Встаньте на Windows 7, x64 машинаПолностью исправьте машину Windows 7Установите Visual Studio 2008Полностью патч Visual Studio 2008Установите Visual Studio 2010Полностью патч Visual Studio 2010Установите Visual Studio 2012Полностью патч Visual Studio 2012

Затем:

Создайте пустой проект "Hello World" под VS2008удалятьвсе Кромеhello_world.cpp (это должно оставить 1 файл решения и 1 файл проекта, 1 исходный файл)Преобразовать его в VS2010Открыть с VS2012

Я могу опубликовать MCVE, который является пустым исходным файлом, чтобы успокоить некоторых людей. Это кажется пустой тратой времени, поскольку проблема связана с цепочкой инструментов, а не с исходным файлом. Пустойmain действительно важно для этой проблемы? НеправильноWINVER а также_WIN32_WINNT будет установлен независимо от того, что находится в файле.

Я знаю причину ошибки. Наш код недавно изменился, чтобы улучшить поддержкуWindows 8, Phone 8, Store 8, Server 2012, Windows 10, Phone 10, Store 10 и универсальная платформа Windows, Изменения выглядят так:

#if defined(CRYPTOPP_WIN32_AVAILABLE)
# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
#  include <synchapi.h>
#  include <ioapiset.h>
#  define USE_WINDOWS8_API
# endif
#endif
...

#if defined(USE_WINDOWS8_API)
    BOOL result = GetOverlappedResultEx(GetHandle(), &m_overlapped, &m_lastResult, INFINITE, FALSE);
#else
    BOOL result = GetOverlappedResult(GetHandle(), &m_overlapped, &m_lastResult, FALSE);
#endif

Как ни странно, мы добавилиUSE_WINDOWS8_API, дополнительные включает в себя и звонки наGetOverlappedResultEx чтобы успокоить инструменты в первую очередь. Они жаловались на устаревшие функции и приводили к грязным компиляциям. Грязные компиляции создавали проблемы управления, C & A и ST & E для пользователей.

Я проверил код, чтобы убедиться, что мы не случайно или неправильно устанавливаем значения. Я проверил, что мы делаем это в одном месте, и путь к коду не активирован, потому что набор инструментов Microsoft устанавливает значение0x602:

#ifdef CRYPTOPP_WIN32_AVAILABLE
# ifndef _WIN32_WINNT
#  define _WIN32_WINNT 0x0400
# endif
#endif

Вот связанный вопрос переполнения стека:Что такое WINVER?, но он не обсуждает, как установить его на «эту платформу».

Вот документы Microsoft на эту тему:Использование заголовков Windows а такжеИзменение WINVER и _WIN32_WINNT, По иронии судьбы, они на самом деле не обсуждают проблему или Windows 10, Windows Phone 10, Windows Store 10 или Windows Universal Platform.

Кроме того, GCC имеет квази-подобный-march=native это в основном обеспечивает "эту платформу".

 jww07 июн. 2016 г., 03:16
@ Андрей - у меня сложилось впечатление, что ты не в курсе этой темыWINVER, _WIN32_WINNT и используя заголовки Windows. Возможно, вам стоит посидеть с этим.
 Andrew Medico07 июн. 2016 г., 03:04
Где находится MVCE?
 jww07 июн. 2016 г., 03:41
@ Андрей - ты не так хорошо разбираешься, как думаешь. В противном случае проблема, с которой мы сталкиваемся, скорее всего, будет для вас устаревшей, и я полагаю, что вы бы подскочили до вашего ответа.
 Harry Johnston08 июн. 2016 г., 06:14
Смотрите такжеstackoverflow.com/a/5440567/886887
 Harry Johnston07 июн. 2016 г., 22:58
Если ваша цель - поддерживать UWP без нарушения рабочего стола,Эта статья Помогите?
 Andrew Medico07 июн. 2016 г., 03:13
Это чепуха. Вы запускаете команды и строите код. Покажите им / это.
 Harry Johnston07 июн. 2016 г., 10:59
Неправильные WINVER и _WIN32_WINNT будут установлены независимо от того, что находится в файле. - Не могли бы вы уточнить, что вы подразумеваете под «неправильно»? Если вы не установили значение самостоятельно, значение по умолчанию должно определяться версией SDK, которую вы используете; это по замыслу, как объясняют ответы Майкла и Чака. (Между прочим, вы понимаете, что должны тестировать свое приложение на машине, на которой нетлюбой версия Visual Studio установлена? В конце концов, именно так его будут использовать большинство конечных пользователей.)
 jww07 июн. 2016 г., 03:10
@ Андрей - что такое MVCE? Мы этого не делаем, так что нечего предложить.
 jww07 июн. 2016 г., 03:02
Для близкого избирателя и нижестоящего избирателя: возможно, вы пропустили это:«Похоже, набор инструментов Microsoft настраивает_WIN32_WINNT в0x602 (_WIN32_WINNT_WIN8)», Мы не устанавливаемWINVER или же_WIN32_WINNT - Набор инструментов Microsoft устанавливает его, и мне не ясно, как предоставить вам что-либо, кроме заявления о том, что мы этого не делаем. Я могу только предоставить доказательства того, что мы реагируем на поддельные ценности Microsoft.
 Harry Johnston07 июн. 2016 г., 11:26
... или вы говорите о библиотеке, и вы хотите создать ее из приложения или аналогичного набора тестов, специально для запуска на вашем компьютере?
 Andrew Medico07 июн. 2016 г., 03:19
Я хорошо разбираюсь, спасибо. Ты тот, у кого проблемы.

Ответы на вопрос(4)

«Эта платформа» подразумевается в наборе инструментов платформы..0 SDK, который по умолчанию_WIN32_WINNT=0x0602 (Windows 8). VS 2013/2015 использует Windows 8.1 SDK, который по умолчанию_WIN32_WINNT=0x0603 (Windows 8.1). Если вы используете VS 2015 и Windows 10 SDK, по умолчанию_WIN32_WINNT=0x0A00 (Windows 10).

Это делается в первую очередь для приложений Магазина Windows / приложений UWP, которым требуется самое последнее значение для_WIN32_WINNT правильно построить. В Windows 10_WIN32_WINNT значение не обновляется от сборки к сборке, поэтому вы указываете, какой параллельный Windows 10 SDK использовать. УвидетьБлог Visual C ++ Team для деталей.

Для настольного приложения Windows (классического Win32) вы должны явно указать, какую версию ОС вы поддерживаете как часть конфигурации вашей сборки. Как правило, это делается вpch.h или другой глобальный заголовок, но это также можно сделать через командную строку сборки / makefile / vcxproj:

#include <WinSDKVer.h>
#define _WIN32_WINNT 0x0600 // Windows Vista SP2 or later
#include <SDKDDKVer.h>

или же

#include <WinSDKVer.h>
#define _WIN32_WINNT 0x0601 // Windows 7 or later
#include <SDKDDKVer.h>

Windows 8.x SDK может быть ориентирован на Windows Vista SP2, Windows 7, Windows 8.0, Windows 8.1 или более позднюю версию.

Если вам нужна поддержка Windows XP с пакетом обновления 3 (SP3) или Windows Server 2003 с пакетом обновления 2 (SP2), вам необходимо использовать альтернативный параметр Platform Toolset, который выбирает Windows 7.1A SDK. Увидетьэта почта для некоторых заметок о различиях.

УвидетьИспользование заголовков Windows а такжеэта статья блога

Имейте в виду, что сама VS 2015 не поддерживает таргетинг Windows 7 RTM, только Windows 7 Service Pack 1.

Для конкретного случаяGetOverlappedResultExЯ использую следующий шаблон в своем коде, который поддерживает сборку как для Windows 7 более низкого уровня, так и для UWP / Windows Store.

    HANDLE hEvent = CreateEventEx( nullptr, nullptr,
        CREATE_EVENT_MANUAL_RESET, EVENT_MODIFY_STATE | SYNCHRONIZE );

...

    // Read and verify header
    OVERLAPPED request = {};
    request.hEvent = hEvent;

    bool wait = false;
    if( !ReadFile( hFile, ..., &request ) )
    {
        DWORD error = GetLastError();
        if ( error != ERROR_IO_PENDING )
            return HRESULT_FROM_WIN32( error );
        wait = true;
    }

    DWORD bytes;
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
    BOOL result = GetOverlappedResultEx( hFile, &request, &bytes, INFINITE, FALSE );
#else
    if ( wait  )
        (void)WaitForSingleObject( hEvent, INFINITE );

    BOOL result = GetOverlappedResult( hFile, &request, &bytes, FALSE );
#endif

Затем я предоставляю несколько сборок моих статических библиотек для каждой поддерживаемой платформы. Помните, что инструмент WACK проверяет ваши таблицы импорта и экспорта EXE / DLL и помечает любые неподдерживаемые API. Таким образом, у вас не может быть выбора времени выполнения, и вы должны ссылаться только на поддерживаемые API в сборках «Windows 8».

 Chuck Walbourn07 июн. 2016 г., 17:50
Ему не нужно перенастраивать свой проект для каждой версии Windows, но он должен иметь отдельные сборки для классического рабочего стола Win32 с поддержкой более низкого уровня по сравнению с UWP, с Windows 8 Store, с Windows 8.1 Store, с Windows phone 8 против Windows phone 8.1. В общем, вы не можете создать один двоичный файл, который будет работать во всех этих случаях. Кстати, на данный момент нет особых причин поддерживать Windows 8.0 Store или Windows phone 8.0 или VS 2012 в целом.

_WIN32_WINNT определить, какой путь кода выбрать, но не устанавливать его. Это подходит для сборок Windows Store / Phone / UWP (как указано в ответе Чака), но не для настольных сборок.

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

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

GetOverlappedResult API не выглядит устаревшим для настольных приложений, поэтому при условии, что вы используетеGetOverlappedResultEx для сборок UWP / Store / Phone вы не должны получать грязные компиляции. (?)

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

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

 Chuck Walbourn07 июн. 2016 г., 06:57
На самом деле это полное законное использование_WIN32_WINNT препроцессор определим. Явное связывание приводит к накладным расходам во время выполнения, и вы все равно не можете использовать явное связывание с UWP. Увидетьэтот блог
 Harry Johnston07 июн. 2016 г., 22:54
@ChuckWalbourn: это хороший момент; в этом конкретном случае, по крайней мере, он даже не использует дополнительную функциональность, предоставляемую более новым API. Я переписал соответственно.
 Harry Johnston07 июн. 2016 г., 09:02
@ChuckWalbourn: разве общие библиотеки не являются особым случаем?
 Chuck Walbourn07 июн. 2016 г., 17:38
Существуют функции и API-интерфейсы, которые стоит проверить и у которых есть запасной вариант с мягким отказом, но они требуют затрат времени выполнения. Этот вид низкоуровневого Win32 API, вероятно, не так.
Решение Вопроса

что (1) в маркетинговой литературе Microsoft говорится, что VS2012 для Windows 7 является поддерживаемой конфигурацией; но (2) инженеры Microsoft утверждают, что это не поддерживаемая конфигурация наПоддержка сообщества MSDN, Минимальная необходимая платформа - Windows 8.

 Harry Johnston09 окт. 2016 г., 02:27
«Поддержка сообщества» не инженеры и не всегда знают, о чем говорят. Если вы перейдете по ссылке в этом ответе, это явно говорит о том, что Windows 7является поддерживается. (Конечно, «поддерживаемый» означает, что он работает как задумано, а не так, как вы хотите.)

Windows SDK выберет версию по умолчанию (подробнее см. Файл SDK sdkddkver.h).

Например, файл SDK для Windows 8.0 sdkddkver.h содержит следующий фрагмент:

#if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)
#define  _WIN32_WINNT   0x0602
#endif

Если вам не нужен этот выбор по умолчанию, вам нужно настроить версию целевой платформы, определив_WIN32_WINNT и / или соответствующие макросы соответственно. Вы можете сделать это с помощью/D Опция компилятора в настройках проекта или make-файле, или вы можете определить его в исходных файлах или в общем заголовке, который включается всем перед включением заголовков SDK.

Что-то вроде/D _WIN32_WINNT=0x0601 может быть подходящим для вас (0x0601 соответствует Win7).

 jww07 июн. 2016 г., 03:47
@ Эндрю - Хорошо, значит, ты один из тех, кто спорит. Какая частьGCC has a quasi-similar -march=native .... был расплывчатым или ты не понимаешь? Я привел вам пример чего-то похожего, что отражает суть «этой платформы».
 Michael Burr07 июн. 2016 г., 17:12
Может быть, я неправильно понимаю что-то о том, что вы хотите сделать, но это, кажется, экстремальный способ исправить то, что можно исправить с помощью настройки проекта / make-файла.
 Andrew Medico07 июн. 2016 г., 03:51
Это было совершенно ясно; Дело в том, что у цепочек инструментов MS нет эквивалента для «целевой версии платформы».
 Harry Johnston08 июн. 2016 г., 23:25
Мой ответ уже объясняет все это - есть определения макросов, которые вы можете использовать для обнаружения сборок Phone / Store / UWP, а для настольных сборок вы либо стремитесь к самой низкой поддерживаемой ОС, либо выбираете API во время выполнения. И если вы не хотите этого делать, и на самом деле запускаете только исполняемый файл на той же машине, на которой его собрали, вы можете использовать шаг перед сборкой. Есть ли что-то, что до сих пор неясно?
 jww07 июн. 2016 г., 12:16
В прошлом мне приходилось редактировать заголовочные файлы Windows, чтобы убрать предупреждения, которые они вводят при/W4 а также/Wall (также см.Выкл. По умолчанию предупреждения). Я думаю, что я, вероятно, собираюсь исправить эти заголовки таким же образом.
 jww07 июн. 2016 г., 03:37
Еще раз спасибо, Майкл. Это тяжело для нас:/D _WIN32_WINNT=0x0601 потому что это заставляет нас сделать неправильный выбор где-то. Если мы установим/D _WIN32_WINNT=0x0601 и пользователь хочет обновить файлы проекта до VS2015 для Windows Store 10, а затем сломать их для них. Я предполагаю, что это будет один из тех вопросов о черной дыре, который не разрабатывает решение, инаш отчет об ошибке по проблеме останется открытым годами.
 Andrew Medico07 июн. 2016 г., 03:16
Наборы инструментов Windows SDK / Microsoft не имеют концепции «этой платформы». У каждого из них есть целевое значение по умолчанию (либо именованная платформа для Windows SDK, либо, как правило, какая-то текущая версия для цепочек инструментов VS). Если вы хотите настроить таргетинг на конкретную ОС, вы либо используете SDK, который предназначен для нее по умолчанию, либо вы должны указать ее.-march совершенно не имеет значения - речь идет о функциях процессора, а не о версии ОС.
 Michael Burr07 июн. 2016 г., 07:45
Я ничего не знаю о проектах, которые создаются для Магазина Windows 10. Но если это другая целевая платформа, то, похоже, вам потребуется другая конфигурация проекта для нее. Укажите правильный_WIN32_WINNT значение для проекта, который строится для этой цели.
 jww07 июн. 2016 г., 03:04
Спасибо, Майкл. Как нам установить его на символическую «эту платформу». Его бесполезно и идиотично устанавливать его на Windows 8 для среды сборки и исполнения Windows 7. Это ломает вещи.
 jww08 июн. 2016 г., 21:54
@MichaelBurr -«Это, кажется, экстремальный способ исправить то, что можно исправить с помощью настройки проекта / make-файла» - Пожалуйста, прости мое невежество ... как мы можем это исправить? Если мы установим это/D _WIN32_WINNT=0x0601 для Windows 7 все сломано для клиентов нижнего и верхнего уровня. У клиентов нижнего уровня, таких как XP, не будет некоторых API. Клиенты верхнего уровня будут пропускать функции. Особенно важно, чтобы клиенты высокого уровня были довольны, потому что Microsoft не хватает важных API наWindows Phone 8 и Windows Store 8.

Ваш ответ на вопрос