Чтобы понять проблему, я думаю, важно понять, что задействованы четыре номера версий :
- (A) Версия файлов заголовков VC, в которую скомпилирован .exe.
- (B) Версия файла манифеста, встроенная в раздел ресурсов этого EXE-файла. По умолчанию этот файл манифеста автоматически создается Visual Studio.
- (C) Версия VD .DLL (часть параллельной сборки), которую вы копируете в тот же каталог, что и .exe.
- (D) Версия файлов манифеста VC (часть параллельной сборки), которую вы копируете в тот же каталог, что и .exe.
В работе находятся две версии DLL-библиотеки VC 2008:
- v1: 9.0.21022.8
- v2: 9.0.30729.4148
Для ясности я буду использовать нотацию v1 / v2. В следующей таблице показан ряд возможных ситуаций:
Situation | .exe (A) | embedded manifest (B) | VC DLLs (C) | VC manifests (D)
-----------------------------------------------------------------------------
1 | v2 | v1 | v1 | v1
2 | v2 | v1 | v2 | v2
3 | v2 | v1 | v2 | v1
4 | v2 | v2 | v2 | v2
Результаты этих ситуаций при запуске .exe в чистой установке Vista SP1:
Ситуация 1: отображается всплывающее окно со словами: «Не удалось найти точку входа в процедуру XYZXYZ в библиотеке динамических ссылок».
Ситуация 2: кажется, ничего не происходит при запуске .exe, но в «Windows Event Viewer / Application log» регистрируется следующее событие:
Сбой генерации контекста активации для «C: \ Path \ file.exe». Ошибка в манифесте или в файле политики «C: \ Path \ Microsoft.VC90.CRT.MANIFEST» в строке 4. Идентификатор компонента, обнаруженный в манифесте, не соответствует идентификатору запрошенного компонента. Ссылка: Microsoft.VC90.CRT, processorArchitecture = "x86", publicKeyToken = "1fc8b3b9a1e18e3b", type = "win32", version = "9.0.21022.8". Определение - Microsoft
Ситуация 3: кажется, все работает нормально. Это решение remicles2 .
Ситуация 4: это как это должно быть сделано . К сожалению, как указывает Роэл, это может быть довольно сложно реализовать.
Теперь моя ситуация (и я думаю, что она такая же, как crashmstr ) - это номер 1. Проблема в том, что Visual Studio по той или иной причине генерирует код клиента (A) для v2, но для по той или иной причине создается файл манифеста v1 (B). Я понятия не имею, где можно настроить версию (A).
Обратите внимание , что все это объяснение все еще находится в контексте частных собраний .
Обновление : наконец-то я начинаю понимать, что происходит. Очевидно, Visual Studio генерирует код клиента (A) для v2 по умолчанию , в отличие от того, что я читал в некоторых блогах Microsoft. Флаг _BIND_TO_CURRENT_VCLIBS_VERSION выбирает только версию в сгенерированном файле манифеста (B), но эта версия будет игнорироваться при запуске приложения.
Заключение
.exe, скомпилированный Visual Studio 2008, по умолчанию ссылается на новейшие версии библиотек VC90. Вы можете использовать флаг _BIND_TO_CURRENT_VCLIBS_VERSION , чтобы контролировать, какая версия библиотек VC90 будет сгенерирована в файле манифеста. Это действительно позволяет избежать ситуации 2, когда вы получаете сообщение об ошибке «манифест не соответствует идентификатору запрошенного компонента». Это также объясняет, почему ситуация 3 работает нормально, поскольку даже без флага _BIND_TO_CURRENT_VCLIBS_VERSION приложение связано с новейшими версиями библиотек VC.
Ситуация еще более странная с открытыми параллельными сборками, где запускался vcredist, помещая библиотеки VC 9.0 в каталог Windows SxS. Даже если в файле манифеста .exe указано, что следует использовать старые версии библиотек DLL (в этом случае флаг _BIND_TO_CURRENT_VCLIBS_VERSION не установлен), Windows по умолчанию игнорирует этот номер версии! Вместо этого Windows будет использовать более новую версию, если она присутствует в системе, за исключением , когда используется «файл конфигурации приложения» .
Я единственный, кто считает, что это сбивает с толку?
Итак в итоге :
- Для частных сборок используйте флаг _BIND_TO_CURRENT_VCLIBS_VERSION в проекте .exe и всех зависимых .lib проектов.
- Для публичных сборок это не требуется, поскольку Windows автоматически выберет правильную версию .DLL из каталога SxS.