从VS2005开始,微软在VC的编译选项中添加了manifest这个功能,这将有助于软件以Side-by-Side方式运行。
采用/MD和/MDd运行时库选项的项目manifest是必要的。当程序启动时发生类似下图找不到MSVCRxxx.dll时可能就是程序没有正确的嵌入清单文件。
怎样给程序嵌入manifest清单?
打开默认的manifest链接功能需要修改两处配置:项目属性→配置属性→链接器→清单文件→生成清单,设置为“是”;项目属性→配置属性→清单工具→输入和输出→嵌入清单,设置为“是”。生成解决方案即可。
若要关闭清单嵌入功能则可将上述选项改为“否”。
找不到MSVCR xxx .dll ?
确认安装了相应版本的VC运行时库。采用/MD和/MDd编译的VC程序运行时需要有VC运行时库可再发行组件包的支持(下载VC可再发行组件包)。你也可以将对应的运行时库dll和应用程序一起打包发布,当然这无疑会增大厂商的发布负担和客户的存贮负担。
确认应用程序正确的嵌入或配置了manifest清单文件。
关键的 Error 14001 ?
用VS自带的错误查找工具得到的解释为:“由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题”。该错误在P/Invoke下表现为Exception from HRESULT: 0x800736B1 。
通常该错误意味着应用程序的依赖dll库找不到或者依赖库的依赖库找不到。用Dependency Walker可以方便的查看应用程序依赖的dll是否存在。补上找不到的dll一般就没啥问题了。一些公用的dll可以从http://www.dll-files.com/获取。
如果发现Dependency Walker的日志窗口出现类似下面的报错,需特别注意:
Error: The Side-by-Side configuration information for "YOUR.DLL" contains errors.This application has failed to start because the application configuration is incorrect.Reinstalling the application may fix this problem (14001).
此时应该确认所以被依赖的dll(包括被间接依赖的dll)中内嵌的manifest所依赖的运行时库都是可用的。如果这些dll所依赖的运行时库是不同的,则应该安装这些依赖的运行时库或将对应的dll拷贝到应用程序所在目录。
可以在VS直接打开exe或者dll文件来导出查看manifest的内容。
一些担当库角色的dll可能是由第三方在很早以前就生成好的,应用程序发布时相应的运行时库可能已经很难获得,要针对每个dll都找到其对应的运行时库版本就更难了。将所有这些不同版本的运行时库都搜集齐并安装给最终用户也实在是一种羞辱,微软早已保证了新版本的运行时库向前兼容。
那,怎么做?怎么做才能让这些早期发布的dll自动绑定到新版本的运行时库?
将manifest过早的嵌入到dll中本身就是一种错误,这种硬绑定直接限制了dll自动升级到新的运行时库,并会导致其他一系列问题。比如,程序将无法从一个模块中申请内存然后在另外一个模块中释放,即使采用的是/MD选项,也因不同版本的运行时库内存管理不在一个堆上,棘手的跨模块的内存管理问题扑面而来。倒!
最好的做法是:仅在一个地方(可执行文件)嵌入manifest来指明运行时库,不要在任何dll中采用manifest。
当然也可以选择非嵌入的manifest,这样后期升级只要手动更改xml文件即可。
参考:
《How to: Deploy using XCopy》
《Redistributing Visual C++ Files》