Сборка и развертывание dll в Windows:SxS, манифесты и все такое прочее
Вопрос
Начиная с VS 2005, я вижу, что невозможно просто создать dll для среды выполнения MS и развернуть их вместе (http://www.ddj.com/windows/184406482).Меня глубоко смущают манифест, SxS и компания:Документация MSDN очень скудна, с циклическими ссылками;тем более, что я больше разбираюсь в Unix, и считаю все это неинформативным.Моя основная проблема заключается в связывании dll с msvc9 или msvc8:поскольку эта среда выполнения не подлежит распространению, каковы шаги по связыванию и развертыванию такой DLL?В частности, как генерируются манифесты (мне не нужен mt.exe, мне нужно что-то переносимое между компиляторами), как они встраиваются и используются?Что означает сборка «бок о бок»?
По сути, где я могу найти какую-либо спецификацию вместо жаргона MS?
Спасибо всем, кто ответил, это было очень полезно,
Решение
Мы используем простой включаемый файл во всех наших приложениях и DLL, vcmanifest.h, а затем устанавливаем во всех проектах встраивание файла манифеста.
vcmanifest.h
/*----------------------------------------------------------------------------*/
#if _MSC_VER >= 1400
/*----------------------------------------------------------------------------*/
#pragma message ( "Setting up manifest..." )
/*----------------------------------------------------------------------------*/
#ifndef _CRT_ASSEMBLY_VERSION
#include <crtassem.h>
#endif
/*----------------------------------------------------------------------------*/
#ifdef WIN64
#pragma message ( "processorArchitecture=amd64" )
#define MF_PROCESSORARCHITECTURE "amd64"
#else
#pragma message ( "processorArchitecture=x86" )
#define MF_PROCESSORARCHITECTURE "x86"
#endif
/*----------------------------------------------------------------------------*/
#pragma message ( "Microsoft.Windows.Common-Controls=6.0.0.0")
#pragma comment ( linker,"/manifestdependency:\"type='win32' " \
"name='Microsoft.Windows.Common-Controls' " \
"version='6.0.0.0' " \
"processorArchitecture='" MF_PROCESSORARCHITECTURE "' " \
"publicKeyToken='6595b64144ccf1df'\"" )
/*----------------------------------------------------------------------------*/
#ifdef _DEBUG
#pragma message ( __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugCRT=" _CRT_ASSEMBLY_VERSION )
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".DebugCRT' " \
"version='" _CRT_ASSEMBLY_VERSION "' " \
"processorArchitecture='" MF_PROCESSORARCHITECTURE "' " \
"publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#else
#pragma message ( __LIBRARIES_ASSEMBLY_NAME_PREFIX ".CRT=" _CRT_ASSEMBLY_VERSION )
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".CRT' " \
"version='" _CRT_ASSEMBLY_VERSION "' " \
"processorArchitecture='" MF_PROCESSORARCHITECTURE "' " \
"publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#endif
/*----------------------------------------------------------------------------*/
#ifdef _MFC_ASSEMBLY_VERSION
#ifdef _DEBUG
#pragma message ( __LIBRARIES_ASSEMBLY_NAME_PREFIX ".MFC=" _CRT_ASSEMBLY_VERSION )
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".MFC' " \
"version='" _MFC_ASSEMBLY_VERSION "' " \
"processorArchitecture='" MF_PROCESSORARCHITECTURE "' " \
"publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#else
#pragma message ( __LIBRARIES_ASSEMBLY_NAME_PREFIX ".MFC=" _CRT_ASSEMBLY_VERSION )
#pragma comment(linker,"/manifestdependency:\"type='win32' " \
"name='" __LIBRARIES_ASSEMBLY_NAME_PREFIX ".MFC' " \
"version='" _MFC_ASSEMBLY_VERSION "' " \
"processorArchitecture='" MF_PROCESSORARCHITECTURE "' " \
"publicKeyToken='" _VC_ASSEMBLY_PUBLICKEYTOKEN "'\"")
#endif
#endif /* _MFC_ASSEMBLY_VERSION */
/*----------------------------------------------------------------------------*/
#endif /* _MSC_VER */
/*----------------------------------------------------------------------------*/
Другие советы
Самое простое, что нужно сделать:Предполагая установку VS2005 по умолчанию, у вас будет такой путь:
C:\Program Files\Microsoft Visual Studio 8\VC\redist\x86\Microsoft.VC80.CRT
Идите, возьмите файлы из этой папки повторного распространения и поместите .manifest И msvcr80.dll (по крайней мере) в папку .exe вашего приложения.Эти файлы, присутствующие в корне вашей установки, должны позволить вашему exe и всем связанным с ним DLL работать безупречно, не прибегая к модулям слияния, MSI или каким-либо видам своевременного обнаружения того, что среда выполнения не установлена.
Вот запись в блоге объяснение причины решения SxS crt для VC++.Он включает в себя объяснение того, насколько плохо статически связывать ЭЛТ и почему не следует этого делать.
Что ж, я столкнулся с некоторыми из этих проблем, поэтому, возможно, некоторые из моих комментариев будут полезны.
- Манифест представляет собой XML-файл.Хотя VS может и сделает его за вас при компиляции, другое решение — создать файл ресурсов (.rc) и скомпилировать его в скомпилированный файл ресурсов (.res) с помощью компилятора ресурсов (rc.exe), включенного в VS. .Вам нужно будет запустить командную строку VS из меню инструментов, в результате чего rc окажется в пути, а также правильно установится различные переменные среды.Затем скомпилируйте свой ресурс.Полученный файл .res может использоваться другими компиляторами.
- Убедитесь, что размер XML-файла манифеста делится на 4.Если необходимо, добавьте пробелы в середине.Старайтесь избегать использования каких-либо символов перед открывающим тегом xml или после закрывающего тега xml.У меня иногда были проблемы с этим.Если вы выполните шаг 2 неправильно, ожидайте появления параллельных ошибок конфигурации.Вы можете проверить, не является ли это вашей ошибкой, открыв exe-файл в редакторе ресурсов (например,devenv.exe) и проверяем ресурс манифеста.Вы также можете увидеть пример правильного манифеста, просто открыв построенный файл, однако учтите, что dll и exe-файлы имеют небольшие различия в том, какой идентификатор должен быть присвоен ресурсу.
Вероятно, вы захотите протестировать его на Vista, чтобы убедиться, что все работает правильно.
Они являются свободно распространяемыми, и у вас есть распространяемые пакеты внутри каталога msvs.
Соберите среду выполнения по вашему выбору, добавьте соответствующий пакет в свой установщик и не беспокойтесь - все будет работать.Разница в том, что они установлен теперь в другом месте (но именно там ваше приложение будет искать библиотеки).
В противном случае MSDN или любая не слишком старая книга по программированию на C++ для Windows.
Спасибо за ответ.Для развертывания как такового я вижу 3 варианта:
- Использование директивы слияния .msi.
- Использование распространяемого пакета VS и запуск его перед моим собственным установщиком.
- Копирование распространяемого файла файлы по моему собственному заявлению.Но как в этом случае мне обратиться к нему в иерархии файловой системы (скажем, bar/foo1/foo1.dll и bar/foo2/foo2.dll относятся к msvcr90.dll в bar/)?Я имею в виду, помимо очевидного и некрасивого «скопировать dll в каждый каталог, где у вас есть dll, которая от нее зависит»).
Вы не можете использовать CRT VC++8 SP1/9 в качестве модуля слияния в Vista и Windows Server 2008, если у вас есть службы, которые вы хотите запустить, или программы, которые вы хотите запустить до действия «InstallFinalize» в MSI.
Это связано с тем, что библиотеки DLL устанавливаются в WinSXS с помощью действия «InstallFinalize».
Но действие MSI «ServiceStart» предшествует этому.
Поэтому используйте либо загрузчик "http://www.davidguyer.us/bmg/publish.htm"
Или изучите использование цепочки установщиков в установщике 4.5.Но это означает, что для установки 4.5 вам понадобится загрузчик, поэтому это кажется немного бессмысленным.
Если вы собираетесь развернуть файлы Microsoft DLLs/.manifest и используете Java JNI, вам нужно будет поместить их в каталог bin вашего JDK/JRE.
Если вы запускаете приложение в JBoss, вам нужно будет поместить их в каталог JBoss/bin.
Вы можете разместить свою JNI DLL там, где это необходимо для вашего приложения.