在Windows上构建和部署dll:SxS,清单和所有爵士乐

时间:2020-03-06 14:30:00  来源:igfitidea点击:

从VS 2005开始,我看到无法简单地针对MS运行时构建dll并将它们一起部署(http://www.ddj.com/windows/184406482)。我对manifest,SxS和co感到非常困惑:MSDN文档确实很差劲,带有循环引用。特别是由于我是Unix方面的家伙,所以我发现所有这些信息都没有意义。我的核心问题是针对msvc9或者msvc8链接dll:由于这些运行时无法重新分发,因此链接和部署此类dll的步骤是什么?特别是清单文件是如何生成的(我不希望mt.exe,我希望这些东西可以在编译器之间移植),它们是如何嵌入,使用的?并排装配是什么意思?

基本上,在哪里可以找到代替MS术语的任何规范?

谢谢所有回答的人,这真的很有帮助,

解决方案

好吧,我遇到了其中一些问题,所以也许我的一些评论会有所帮助。

  • 清单是一个xml文件。虽然VS在编译时可以为我们提供帮助,但另一种解决方案是生成资源文件(.rc),并使用VS随附的资源编译器(rc.exe)将其编译为已编译的资源文件(.res)。 。我们将需要从工具菜单运行VS命令行,这将导致rc位于路径中,以及正确设置各种环境变量。然后编译资源。生成的.res文件可以由其他编译器使用。
  • 确保清单XML文件的大小可被4整除。如果需要,请在文件中间添加空格以实现此目的。尝试避免在打开xml标记之前或者关闭xml标记之后包含任何字符。我有时对此有疑问。如果我们错误地执行了步骤2,则可能会遇到并行配置错误。我们可以通过在资源编辑器(例如devenv.exe)中打开exe并检查清单资源来检查这是否是错误。我们还可以通过打开一个构建文件来查看正确清单的示例,但是请注意,dll和exe在应提供资源的id上有微小的差异。

我们可能需要在Vista上进行测试,以确保其正常运行。

它们是可重新分发的,并且我们在msvs目录中具有可重新分发的软件包。

使用我们选择的运行时进行构建,将相应的软件包添加到安装程序中,不要打扰它会起作用。不同之处在于它们现在安装在不同的位置(但这也是应用程序要查找库的位置)。

否则,MSDN或者基本上所有关于Windows c ++编程的书都不会太老。

这是博客条目,解释了VC ++的SxS crt决策背后的原因。它包括说明静态链接crt有多糟糕,以及为什么不应该这样做。

这是有关如何静态链接crt的文档。

感谢回答。对于部署本身,我可以看到3个选项,然后:

  • 使用.msi merge指令。
  • 使用可重新分发的VS软件包并在我自己的安装程序之前运行它
  • 沿着我自己的应用程序复制可再发行文件。但是在这种情况下,如何在文件系统层次结构中引用它(例如,bar / foo1 / foo1.dll和bar / foo2 / foo2.dll在bar /中引用msvcr90.dll)?我的意思是,除了明显且难看的"将dll复制到我们依赖它的dll所在的每个目录中"。

我们在所有应用程序和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 */

/*----------------------------------------------------------------------------*/

如果我们有要启动的服务或者要在MSI中执行" InstallFinalize"操作之前要运行的程序,则不能将VC ++ 8 SP1 / 9 CRT用作Vista和Windows Server 2008上的合并模块。

这是因为dll是通过" InstallFinalize"操作安装在WinSXS中的。

但是,MSI" ServiceStart"操作是在此之前执行的。

因此,请使用引导程序" http://www.davidguyer.us/bmg/publish.htm"

或者考虑使用安装程序4.5中的安装程序链接。但这意味着我们需要一个引导程序才能安装4.5,因此似乎毫无意义。

最简单的操作:
假设默认安装的是VS2005,我们将具有以下路径:

C:\Program Files\Microsoft Visual Studio 8\VC\redist\x86\Microsoft.VC80.CRT

去,抓住这个redist文件夹中的文件,然后将.manifest和msvcr80.dll(至少)放在应用程序.exe文件夹中。
这些文件出现在安装的根目录中,应该可以使exe和与其链接的所有dll正常运行,而无需诉诸合并模块,MSI或者实际上任何及时的未安装运行时检测。

如果打算部署Microsoft DLLs / .manifest文件并使用Java JNI,则需要将它们放在JDK / JRE的bin目录中。

如果我们正在JBoss中运行该应用程序,则需要将它们放在JBoss / bin目录中。

我们可以将JNI DLL放在适合应用程序的位置。