Подтвердить что ты не робот

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

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

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

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

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

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

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

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

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

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

Параметры:

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

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

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

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

Разве никто не должен был разбираться с этой проблемой?

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

4b9b3361

Ответ 1

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

Я на 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 не используется ничего, кроме связанных с ним библиотек.

Ответ 2

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

  • (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".Error в файле манифеста или политики "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: это как это сделать. К сожалению, как показывает Roel, его довольно сложно реализовать.

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

Обратите внимание, что все это объяснение по-прежнему находится в контексте личных ассемблеров.

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

Заключение

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

Ситуация еще более странная с публичными бок о бок-сборками, где был запущен 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.

Ответ 3

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

Ответ 4

Другим приятным инструментом для просмотра exe и dll-манифеста является "Манифест" , который, по всей видимости, не будет работать на чистой установке XP, потому что это зависит от 9.0.21022.

Ответ 5

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

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

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

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