代码之家  ›  专栏  ›  技术社区  ›  David Cournapeau

在windows上构建和部署dll:SxS、清单等等

  •  3
  • David Cournapeau  · 技术社区  · 16 年前

    自VS2005以来,我发现不可能简单地针对MS运行时构建dll并将它们一起部署( http://www.ddj.com/windows/184406482 )。我对清单、SxS和co深感困惑:MSDN文档非常糟糕,带有循环引用;特别是因为我更喜欢Unix,所以我发现所有这些都没有信息。我的核心问题是将dll链接到msvc9或msvc8:既然这些运行时是不可再分发的,那么链接和部署这样一个dll的步骤是什么?特别是,清单是如何生成的(我不想要mt.exe,我想要跨编译器移植的东西),它们是如何嵌入和使用的?并排装配是什么意思?

    基本上,我在哪里可以找到任何类型的规范而不是MS术语?

    谢谢大家的回答,这真的很有帮助,

    8 回复  |  直到 16 年前
        1
  •  3
  •   titanae    16 年前

    我们在所有应用程序中使用一个简单的include文件&然后将所有项目设置为嵌入清单文件。

    vcsmanifest.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 */
    
    /*----------------------------------------------------------------------------*/
    
        2
  •  3
  •   Chris Becke    16 年前

    最简单的做法是: 假设默认安装VS2005,您将有如下路径:

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

    这些文件存在于安装的根目录中,应该使您的exe和所有与它们链接的DLL能够完美地工作,而无需借助合并模块、MSI或任何类型的即时检测来检测运行时是否未安装。

        3
  •  2
  •   Steve Steiner    16 年前

    explaining the rational behind the SxS crt decision for VC++ . 它包括解释静态链接crt有多糟糕,以及为什么不应该这样做。

    这是你的电话号码 documentation on how to statically link the crt

        4
  •  2
  •   Nicolás    11 年前

    嗯,我遇到了其中一些问题,所以我的一些评论可能会有所帮助。

    1. 确保清单xml文件的大小可以被4整除。如果需要的话,在中间添加空白。尽量避免在打开xml标记之前或关闭xml标记之后出现任何字符。我有时会遇到这样的问题。如果您错误地执行步骤2,则可能会出现并行配置错误。您可以通过在资源编辑器(例如devenv.exe)中打开exe并检查清单资源来检查这是否是您的错误。只需打开一个构建文件,您就可以看到一个正确清单的示例,不过请注意,DLL和EXE在应该为资源指定的id方面有微小的差异。

    您可能需要在Vista上进行测试,以确保其正常工作。

        5
  •  1
  •   ima    16 年前

    它们是可再发行的,在msvs目录中有可再发行的包。

    现在在另一个地方(但这也是你的应用程序寻找库的地方)。

    否则,MSDN或基本上任何一本不太老的Windows C++编程书籍。

        6
  •  0
  •   David Cournapeau    16 年前

    谢谢你的回答。就部署本身而言,我可以看到3个选项,然后:

    • 使用可再发行的VS包并在我自己的安装程序之前运行它
    • 文件夹
        7
  •  0
  •   garthy    16 年前

    如果在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,所以它看起来有点毫无意义。。

        8
  •  0
  •   EricJ    16 年前

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

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