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

从VS 2005开始,我发现不可能简单地针对MS运行时构build一个DLL并将其部署在一起( http://www.ddj.com/windows/184406482 )。 我对表单SxS和Co深感困惑:MSDN文档非常差,带有循环引用; 特别是因为我更像一个Unix的家伙,我发现所有这些都是不知情的。 我的核心问题是链接到msvc9或msvc8 DLL:因为这些运行时不可重新分发,有什么步骤来链接和部署这样一个DLL? 特别是,如何生成清单(我不想mt.exe,我想要在编译器中移植的东西),它们是如何embedded,使用的? 并排组装是什么意思?

基本上,我在哪里可以find任何types的规范,而不是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 

去抓取这个redist文件夹中的文件,并将.manifest和msvcr80.dll(至少)放到你的应用程序的.exe文件夹中。 这些文件存在于你的安装根目录下,它可以使你的exe和所有链接到它们的dll无懈可击地工作,而不需要合并模块,MSI或任何种类的运行时没有安装的即时检测。

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

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

那么,我遇到了一些这些问题,所以也许我的一些评论会有所帮助。

  1. 清单是一个xml文件。 当VS编译时,VS可以并且会为你制作一个,另一个解决方案是使用VS中包含的资源编译器(rc.exe)生成一个资源文件(.rc)并将其编译成编译的资源文件(.res) 。 你需要从工具菜单中运行VS命令行,这会导致rc在路径中,并正确设置各种环境变量。 然后编译你的资源。 其他编译器可以使用生成的.res文件。
  2. 确保你的manifest.xml文件的大小可以被4整除。如果需要的话,在它的中间添加空格来实现这个功能。 尽量避免在打开xml标签之前或关闭xml标签之后有任何字符。 我有时有这个问题。 如果您错误地执行了第2步,则希望得到并排的配置错误。 您可以通过在资源编辑器(例如devenv.exe)中打开exe文件并检查清单资源来检查是否是您的错误。 你也可以通过打开一个构建的文件来看到一个正确的清单的例子,但是请注意,dll和exes在资源应该给予的id上略有不同。

你可能会想要在Vista上测试,以确保这是正常工作。

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

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

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

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

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

如果您有要启动的服务或在MSI中的“InstallFinalize”操作之前要运行的程序,则无法将VC ++ 8 SP1 / 9 CRT用作Vista和Windows server 2008上的合并模块。

这是因为在“InstallFinalize”操作中将DLL安装在WinSXS中。

但MSI“ServiceStart”动作在此之前。

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

或者查看使用安装程序4.5中的安装程序。 但这意味着你需要一个引导程序来安装4.5,所以它看起来有点没有意义。

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

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

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