Алексей Иванов (alexyv) wrote,
Алексей Иванов
alexyv

Category:
  • Mood:
  • Music:

Side-by-side assemblies и их проблемы

На прошлой неделе столкнулся с интересной проблемой DLL Hell'а.

Чтобы решить проблему с библиотеками, в Windows XP появился механизм side-by-side assemblies. В системе может быть установлено несколько версий одной и той же библиотеки, а каждое приложение должно явным образом указать, какую версию следует загрузить. Такой механизм явного объявления зависимостей устраняет ошибки из-за загрузки несовместимой версии библиотеки.

Но не все так гладко… Начиная с Visual Studio 2005, библиотеки С++ runtime поставляются в виде side-by-side assemblies, а компилятор/линкер автоматически создают manifest файл, в котором указываются эти зависимости.

Проблемы возникают, когда приложение использует DLL, которые собираются не из исходного кода. Например, если приложение и используемые библиотеки были откомпилированы разными версиями Visual Studio, в системе должны будут находится две (или даже больше) разных версий C++ runtime.

Вот именно с такой проблемой я и столкнулся. Сначала обнаружилось, что у нас две зависимости: от версии 8.0.50608.0 и от 8.0.50727.762. А через несколько дней среди зависимостей вдруг появилась еще и третья версия 8.0.50727.4053.

Раньше библиотеки Visual C++ вместе с манифестом лежали в папке с остальными библиотеками, и всё работало. (То есть они использовались как private assembly.) Недавно выяснилось впрочем, что не совсем всё работало: обнаружилось, что на тестовых машинах были установлены библиотеки версии 8.0.50727.42. А если вдруг их не оказывалось, то ничего не запускалось.

Две разных версии assembly не могут одновременно находится в папке с приложением, потому что файлы называются одинаково. Как обойти это, описано в статье A solution to two references to different versions of CRT, MFC, ATL in one application manifest file. Workaround #2 не помогал, потому что зависимости росли не из EXE-файла, а из DLL. В комментариях нашлось решение и для DLL, которое более подробно описано здесь. После добавления файликов <dll-name>.2.config приложение заработало.

Но с появлением зависимости от третьей версии, которая появилась после установки обновления, пришлось бы создавать такие файлы почти для каждой DLL-библиотеки, а их не мало. В итоге, чтобы жизнь была проще, был выбран первый вариант решения: использование Merge-модулей, тем более для установки уже использовался Windows Installer. Merge-модули устанавливают не только сами библиотеки, но и policy-файл, который «перенаправляет» предыдущие версии на новую версию. Таким образом, поставка всего одной версии библиотек и установка глобальной политики перенаправления версий решило все проблемы с зависимостями и избавило от создания кучи config-файлов с одинаковым содержанием.

На эти исследования пришлось потратить почти два дня, зато теперь в арсенале имеются новые знания.

Tags: msi, windows, программирование, работа
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 19 comments