Сборка и развертывание dll в Windows:SxS, манифесты и все такое прочее

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

  •  02-07-2019
  •  | 
  •  

Вопрос

Начиная с 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++.Он включает в себя объяснение того, насколько плохо статически связывать ЭЛТ и почему не следует этого делать.

Здесь документация о том, как статически связать crt.

Что ж, я столкнулся с некоторыми из этих проблем, поэтому, возможно, некоторые из моих комментариев будут полезны.

  1. Манифест представляет собой XML-файл.Хотя VS может и сделает его за вас при компиляции, другое решение — создать файл ресурсов (.rc) и скомпилировать его в скомпилированный файл ресурсов (.res) с помощью компилятора ресурсов (rc.exe), включенного в VS. .Вам нужно будет запустить командную строку VS из меню инструментов, в результате чего rc окажется в пути, а также правильно установится различные переменные среды.Затем скомпилируйте свой ресурс.Полученный файл .res может использоваться другими компиляторами.
  2. Убедитесь, что размер 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 там, где это необходимо для вашего приложения.

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