Правильное создание релизной версии проекта в Visual Studio

Первое, в чем необходимо убедиться - что программа не использует функции, которые могут

отсутствовать на целевых версиях Windows. Например, InitializeCriticalSectionEx поддерживается,

начиная с Windows Vista, а CreateFile2 вообще есть только на Windows 8 и Windows Server 2012.

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

Следующий фрагмент разрешает включать из стандартных заголовков SDK только те объявления,

которые имеют смысл для Windows XP (0x0501 - это номер версии NT для Windows XP (5.1), а

0x0600 - это версия Internet Explorer для этой системы, в данном случае шестая):

CВыделить код

1
2
3
4

#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define _WIN32_WINDOWS 0x0501
#define _WIN32_IE 0x0600

Этот код должен быть включен до любых директив #include. Обычно его выносят в один общий

заголовок с соответствующим названием, например targetver.h (target version).

Теперь при попытке использовать функцию, доступную только на более новых, чем Windows XP,

системах, будет выдана ошибка компиляции.

Это не панацея, но решение 90% проблем данного класса. Хотя некоторые все равно останутся.

Например exe, собранный в Visual C++ 2010, имеет зависимость от функций EncodePointer и

DecodePointer, и поэтому не запустится на Windows Server 2003 RTM (который без R2 и без

сервис-пака), так как на данной системе эти функции отсутствуют. А вот Visual C++ 2008

такой проблемы не имел.

Бывает, что программе, если она запускается на новых системах, нужны некоторые новые

функции, в этом случае следует определять номер версии Windows (GetVersionEx) и

загружать необходимые dll динамически - LoadLibrary/GetProcAddress.

При этом следует учитывать, что программа может быть запущена в режиме совместимости.

Второе - проверить, что программа не имеет зависимостей от dll, которые могут отсутствовать

на целевых системах. Распостраненный случай - отсутствие нужной версии Visual C++ Runtime.

В Visual C++ 2008 рантайм был сделан как SxS-сборки и его нужно было либо включать в инстяллятор

программы, как Merge Module или vcredist.exe, либо делать в каталоге с установленной программой

дополнительную подпапку со специальным именем и помещать сборку туда. В Visual C++ 2010 решение

проблемы упростили и рантайм (msvcr100.dll/msvcp100.dll) теперь подключается, как обычная dll,

без манифестов и прочих сложностей. Хотя вы можете по-прежнему включать в инсталлятор программы

Visual C++ 2010 Redistributable, он просто скопирует файлы рантайма в папку Windows\system32.

Ключ /MT компилятора тоже может помочь, в этом случае рантайм подключается статически и

зависимостей от msvcr100.dll/msvcp100.dll не будет. Хотя данный способ не всегда возможен.

Если проблема остается, можно воспользоваться утилитой Dependency Walker:

http://www.dependencywalker.com/

Запускайте ее на проблемной системе и смотрите, каких dll не хватает.

Еще находить проблемы совместимости очень помогает использование виртуальных машин.

Можно сделать себе целый "зоопарк" разных виртуальных систем и конфигураций и перед каждым

релизом софта тестировать его на этих системах.