Приложение не запускается с библиотеками DLL VS 2008 SP1, предыдущая версия работает с версиями RTM

StackOverflow https://stackoverflow.com/questions/59635

  •  09-06-2019
  •  | 
  •  

Вопрос

С момента нашего перехода с Visual Studio 6 на Visual Studio 2008 мы используем MFC90.dll и msvc [pr]90.dll вместе с файлами манифеста в частной параллельной конфигурации, чтобы не беспокоиться о версиях или их установке в систему.

До выпуска SP1 это работало нормально (и до сих пор отлично работает на наших компьютерах разработчиков).Теперь, когда мы провели некоторое тестирование после выхода SP1, я со вчерашнего утра выдергиваю из себя волосы.

Во-первых, наш установочный скрипт NSIS извлекает библиотеки DLL и файлы манифеста из папки redist.Они больше не были корректными, так как приложение по-прежнему ссылается на RTM-версию.

Поэтому я добавил определение для _BIND_TO_CURRENT_VCLIBS_VERSION=1 ко всем нашим проектам, чтобы они использовали библиотеки DLL с пакетом обновления 1 в папке redist (или последующие библиотеки по мере выхода новых пакетов обновления).Мне потребовались часы, чтобы найти это.

Я дважды проверил сгенерированные файлы манифеста в папке промежуточных файлов из компиляции, и в них правильно указаны версии 9.0.30729.1 SP1.Я дважды и трижды проверял, зависит от чистоты машины:все это ссылается на локальные библиотеки dll без ошибок.

Запуск приложения по-прежнему выдает следующую ошибку:

Приложению не удалось правильно инициализироваться (0xc0150002).Нажмите на кнопку ОК, чтобы завершить работу приложения.

Ни один из поисковых запросов, которые я выполнял в Google или Microsoft, не выявил ничего, что имело бы отношение к моим конкретным проблемам (но есть обращения к 2005 году с этим сообщением об ошибке).

У кого-нибудь была подобная проблема с SP1?

Опции:

  • Найдите проблему и устраните ее, чтобы она работала должным образом (предпочтительно)
  • Установите повторный список
  • откопайте старые библиотеки DLL RTM и файлы манифеста и удалите #define, чтобы использовать текущие.(Я получил их в более ранней сборке установщика, поскольку Microsoft удалила их из вашей папки redist!)

Редактировать: Я пробовал повторную сборку с отключенным определением (ссылка на библиотеки RTM dll), и это работает до тех пор, пока библиотеки RTM dll установлены в папке.Если будут удалены библиотеки DLL SP1, появится следующая ошибка:

c:\Program Files\...\...\X.exe

Этому приложению не удалось запуститься из-за неправильной конфигурации приложения.Переустановка приложения может устранить эту проблему.

Неужели никому больше не приходилось сталкиваться с этой проблемой?

Редактировать: Просто для усмешки я скачал и запустил vcredist_x86.exe для VS2008SP1 на своей тестовой машине. IT работает.С библиотеками DLL SP1.И мое приложение, связанное с RTM.Но НЕТ в частном параллельном дистрибутиве, который работал до выпуска SP1.

Это было полезно?

Решение

Я сам боролся с этой проблемой на прошлой неделе и сейчас считаю себя в некотором роде экспертом ;)

Я на 99% уверен, что не все библиотеки DLL и статические библиотеки были перекомпилированы с версией SP1.Вам нужно поместить

#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

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

Есть и другие флаги, которые определяют, к каким версиям привязываться;это задокументировано на http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspx .В качестве альтернативы приведенным выше строкам вы также можете поместить

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

который будет привязан к последней версии всех библиотек VC (CRT, MFC, ATL, OpenMP).

Затем проверьте, что говорится во встроенном манифесте.Скачать Редактор ресурсов XM: http://www.wilsonc.demon.co.uk/d10resourceeditor.htm.Откройте все библиотеки DLL и exe в вашем решении.Посмотрите в разделе "Манифест темы XP".Убедитесь, что атрибут 'version' с правой стороны равен '9.0.30729.1'.Если это "9.0.21022", то какая-то статическая библиотека загружает манифест для старой версии.

Что я обнаружил, так это то, что во многих случаях, и то , и другое версии были включены в манифест.Это означает, что некоторые библиотеки используют версию sp1, а другие - нет.

Отличный способ отладить, в каких библиотеках не установлены директивы препроцессора:временно измените заголовки вашей платформы, чтобы компиляция останавливалась при попытке внедрить старый манифест.Откройте C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h.Найдите строку '21022'.В этом определении укажите что-нибудь недопустимое (измените "define" на "blehbleh" или около того).Таким образом, когда вы компилируете проект, в котором _BIND_TO_CURRENT_CRT_VERSION флаг препроцессора не установлен, ваша компиляция остановится, и вы узнаете, что вам нужно добавить их или убедиться, что это применяется везде.

Также обязательно используйте Dependency Walker, чтобы вы знали, какие библиотеки DLL загружаются.Проще всего установить свежую копию Windows XP без обновлений (только SP2) на виртуальную машину.Таким образом, вы точно знаете, что в папке SxS нет ничего, что использовалось бы вместо параллельных библиотек DLL, которые вы предоставили.

Другие советы

Чтобы понять проблему, я думаю, важно осознать, что существуют задействованы четыре номера версий:

  • (A) Версия заголовочных файлов VC, в которые компилируется .exe.
  • (B) Версия файла манифеста, который встроен в раздел ресурсов этого .exe.По умолчанию этот файл манифеста автоматически создается Visual Studio.
  • (C) Версия VC .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 / журнал приложений":

    Не удалось сгенерировать контекст активации для "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 от remicles2.

  • Ситуация 4:это как это должно быть сделано.К сожалению, как указывает Роэл, это может быть довольно сложно реализовать.

Теперь моя ситуация (и я думаю, что она такая же, как crashmstr-х) является номером 1.Проблема в том, что Visual Studio по той или иной причине генерирует клиентский код (A) для версии v2, но по той или иной причине генерирует файл манифеста версии v1 (B).Я понятия не имею, где можно настроить версию (A).

Примечание что все это объяснение все еще находится в контексте частные собрания.

Обновить:наконец-то я начинаю понимать, что происходит.Очевидно, Visual Studio по умолчанию генерирует клиентский код (A) для версии v2, вопреки тому, что я читал в некоторых блогах Microsoft.Флаг _BIND_TO_CURRENT_VCLIBS_VERSION выбирает только версию в сгенерированном файле манифеста (B), но эта версия будет игнорироваться при запуске приложения.

Заключение

Исполняемый файл, скомпилированный Visual Studio 2008, по умолчанию ссылается на новейшие версии библиотек DLL VC90.Ты можешь используйте флаг _BIND_TO_CURRENT_VCLIBS_VERSION чтобы определить, какая версия библиотек VC90 будет сгенерирована в файле манифеста.Это действительно позволяет избежать ситуации 2, когда вы получаете сообщение об ошибке "манифест не соответствует идентификатору запрошенного компонента".Это также объясняет, почему ситуация 3 работает нормально, поскольку даже без флага _BIND_TO_CURRENT_VCLIBS_VERSION приложение связано с новейшими версиями библиотек DLL VC.

Ситуация еще более странная с общедоступными параллельными сборками, где был запущен vcredist, помещающий библиотеки DLL VC 9.0 в каталог Windows SxS.Даже если в файле манифеста .exe указано, что следует использовать старые версии библиотек DLL (это тот случай, когда флаг _BIND_TO_CURRENT_VCLIBS_VERSION не установлен), Windows игнорирует этот номер версии установлен по умолчанию!Вместо этого Windows будет использовать более новую версию, если она присутствует в системе, за исключением когда "файл конфигурации приложения" используется.

Неужели я единственный, кто считает, что это сбивает с толку?

Итак подводя итог:

  • Для частных сборок используйте флаг _BIND_TO_CURRENT_VCLIBS_VERSION в проекте .exe и ВСЕ зависимые проекты .lib.
  • Для общедоступных сборок это не требуется, поскольку Windows автоматически выберет правильную версию .Библиотеки DLL из каталога SxS.

Я только что вспомнил еще один трюк, который я использовал, чтобы выяснить, какие статические библиотеки плохо себя вели:'grep' через статические библиотеки для строки '21022'.ОДНАКО не используйте "обычные" инструменты grep, такие как wingrep, потому что они не покажут вам эти строки (они думают, что это двоичный файл, и ищут необработанную строку, отличную от unicode).Используйте утилиту 'strings' из набора ресурсов (я думаю, сейчас на сайте Russinovich).Этот будет работать с grep через двоичные файлы нормально.Итак, вы пропускаете эти "строки" через все ваше дерево исходных текстов, и вы увидите двоичные файлы (DLL и статические библиотеки), которые содержат ссылки на неправильный манифест (или на манифест с неверной версией в нем).

Еще одним приятным инструментом для просмотра манифестов exe и dll является Вид Манифеста, который, как ни странно, не будет запускаться при чистой установке XP, потому что IT зависит от версии 9.0.21022.

Что касается вашего третьего варианта, вы, вероятно, можете найти библиотеки DLL и манифесты для версии 9.0.21022 в каталоге C:\WINDOWS\WinSxS на вашем компьютере разработчика.Если вы можете, то можете настроить свой собственный каталог redist и установить эти файлы вместе со своим приложением.

В качестве альтернативы вы можете использовать библиотеки 9.0.30729.1, поставляемые с Visual Studio, и подделать манифест, который вы устанавливаете вместе со своим приложением, чтобы сообщить, что оно предоставляет библиотеки DLL 9.0.21022, а не 9.0.30729.1.Компоновщик среды выполнения, похоже, не возражает.Видишь это Блог, который был чрезвычайно полезен для решения этих проблем, для получения дополнительной информации.

Оба обходных пути устранили проблемы, которые у меня были при развертывании библиотек DLL в виде частных сборок с VS2008 Express.

Ответ Роэла - это путь для вашего первого варианта ("исправьте это правильно"), но если вы зависите от библиотеки, которая зависит от 9.0.21022 (и поэтому в вашем манифесте перечислены обе версии), то третий вариант может быть единственным способом, если вы не хотите запускать vcredist_x86.exe .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top