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

После перехода с 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 SP1 в папке redist (или последующих, по мере выхода новых пакетов обновления). На это у меня ушло несколько часов.

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

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

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

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

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

Options:

  • Find the problem and fix it so it works as it should (preferred)
  • Install the redist
  • dig out the old RTM dlls and manifest files and remove the #define to use the current ones. (I've got them in an earlier installer build, since Microsoft blasts them out of your redist folder!)

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

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

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

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

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


person crashmstr    schedule 12.09.2008    source источник


Ответы (5)


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

Я на 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». Убедитесь, что атрибут «версия» справа равен «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, чтобы знать, какие библиотеки втягиваются. Проще всего установить новую копию Windows XP без обновлений (только SP2) на виртуальной машине. Таким образом, вы точно знаете, что в папке SxS нет ничего, что использовалось бы вместо предоставленных вами параллельных DLL.

person Roel    schedule 16.09.2008
comment
Depends никогда не показывал, чего не хватало на моей чистой виртуальной машине (возможно, нужно убедиться, что у меня установлена ​​последняя версия!), Но с помощью редактора ресурсов я обнаружил проблемную DLL. Это была DLL, которую мы скомпилировали, но она не является частью нашего проекта. Спасибо за помощь. - person crashmstr; 16.09.2008
comment
Я получил более новую версию Dependency Walker, и она немедленно выявила проблемы с конкретными DLL, которые были проблемой. - person crashmstr; 16.09.2008
comment
Техника редактирования Роэля crtassem.h отлично подходит для поиска единиц компиляции, которые не включают stdafx.h, которые все еще могут связывать неправильные версии библиотеки. - person Aidan Ryan; 28.04.2011
comment
Поднимает руки к небу Спасибо, спасибо, спасибо! Мало того, что это сработало, я действительно понимаю, почему. Комбинация sxstrace для определения, какой компонент кричит о зависимости sxs, и эти определения, чтобы указать на манифест в правильном направлении, woot! - person Erikest; 29.04.2014

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

  • (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 регистрируется следующее событие:

    Ошибка создания контекста активации для «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's) номер 1. Проблема в том, что Visual Studio для по той или иной причине генерируется клиентский код (A) для v2, но по той или иной причине генерируется файл манифеста v1 (B). Понятия не имею, где можно настроить версию (A).

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

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

Вывод

Файл .exe, скомпилированный 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.
person Community    schedule 28.01.2010
comment
Какая ирония в том, что эта MESS должна решить аду DLL. Теперь у нас ад SxS, что еще хуже. - person Tamás Szelei; 30.06.2011

Я только что вспомнил еще один трюк, который использовал, чтобы выяснить, какие статические библиотеки плохо себя ведут: «grep» через статические библиотеки для строки «21022». ОДНАКО не используйте «обычные» инструменты grep, такие как wingrep, потому что они не покажут вам эти строки (они думают, что это двоичный файл, и ищут необработанную строку, отличную от Unicode). Воспользуйтесь утилитой 'strings' из набора ресурсов (кажется, сейчас на сайте Руссиновича). Этот будет нормально перебирать двоичные файлы. Таким образом, вы позволяете этим «строкам» проходить через все ваше исходное дерево, и вы увидите двоичные файлы (dll и статические библиотеки), которые содержат ссылки на неправильный манифест (или на манифест с неправильной версией в нем).

person Roel    schedule 16.09.2008

Еще один хороший инструмент для просмотра манифестов exe и dll - это Manifest View, который, соответственно, не будет работать при чистой установке XP, потому что он зависит от 9.0.21022.

person remcycles    schedule 14.10.2009

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

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

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

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

person remcycles    schedule 14.10.2009