3

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

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

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

4

8 回答 8

3

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

/*----------------------------------------------------------------------------*/
于 2008-09-22T03:20:49.027 回答
3

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

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

去,抓取这个 redist 文件夹中的文件,然后将 .manifest 和 msvcr80.dll(至少)放在您的应用程序 .exe 文件夹中。这些文件存在于安装的根目录中,应该使您的 exe 和所有链接到它们的 dll 能够完美地工作,而无需借助合并模块、MSI 或任何类型的运行时未安装的即时检测。

于 2008-10-22T14:21:56.147 回答
2

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

  1. 清单是一个 xml 文件。虽然 VS 可以并且会在您编译时为您制作一个,但另一种解决方案是生成一个资源文件 (.rc) 并使用 VS 附带的资源编译器 (rc.exe) 将其编译为已编译的资源文件 (.res) . 您需要从工具菜单运行 VS 命令行,这将导致 rc 位于路径中,并正确设置各种环境变量。然后编译你的资源。生成的 .res 文件可供其他编译器使用。
  2. 确保您的清单 xml 文件的大小可被 4 整除。如果需要,在其中间添加空格以实现此目的。尽量避免在开始 xml 标记之前或在结束 xml 标记之后出现任何字符。我有时对此有疑问。如果您不正确地执行第 2 步,预计会出现并排配置错误。您可以通过在资源编辑器(例如 devenv.exe)中打开 exe 并检查清单资源来检查这是否是您的错误。您还可以通过打开构建文件来查看正确清单的示例,但请注意,dll 和 exe 在应提供资源的 id 方面存在微小差异。

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

于 2008-09-21T04:46:53.477 回答
2

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

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

于 2008-09-21T05:29:23.500 回答
1

它们是可再分发的,并且您在 msvs 目录中有可再分发的包。

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

否则,MSDN 或基本上任何不太老的关于 windows c++ 编程的书。

于 2008-09-21T04:49:59.447 回答
0

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

  • 使用 .msi 合并指令。
  • 使用可再发行的 VS 包并在我自己的安装程序之前运行它
  • 沿着我自己的应用程序复制可再发行文件。但在这种情况下,我如何在文件系统层次结构中引用它(比如 bar/foo1/foo1.dll 和 bar/foo2/foo2.dll 在 bar/ 中引用 msvcr90.dll)?我的意思是除了明显和丑陋的“将dll复制到你拥有依赖它的dll的每个目录中)。
于 2008-09-21T08:36:14.957 回答
0

如果您有要启动的服务或要在 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,所以这似乎有点毫无意义..

于 2008-10-16T16:19:14.447 回答
0

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

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

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

于 2009-05-07T16:05:48.710 回答