最近公司软件windows客户端在安装的时候遇到直接闪退的问题。最后查出来是vc运行时库版本比我们的低。为了指定特定版本的vc运行时库就像到了manifest文件。
Manifest
Manifests are XML files that accompany and describe side-by-side assemblies or isolated applications. —— [ MSDN ]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--This Id value indicates the application supports Windows Vista functionality -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--This Id value indicates the application supports Windows 7 functionality-->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--This Id value indicates the application supports Windows 8 functionality-->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--This Id value indicates the application supports Windows 8.1 functionality-->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
</application>
</compatibility>
<assemblyIdentity type="win32"
name="myOrganization.myDivision.mySampleApp"
version="6.0.0.0"
processorArchitecture="x86"
publicKeyToken="0000000000000000"
/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32"
name="Proseware.Research.SampleAssembly"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="0000000000000000"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
这里根据MSDN的说明了解到manifest文件其实就是一个xml文件,用来指定应用程序(包括DLL)需要的动态库版本还有需要的系统权限等。
了解到了这些就直接开干吧。
使用的是VS2013 右键项目属性可以看到生成清单是默认的,可以用notepad打开应用程序,然后拉到最后就会看到一个内嵌manifest文件内容
这里我们可以直接看到附加清单依赖项。按照我们上面看到的manifest文件的示例,加上如下一段代码。这里我是想指定应用程序加载制定版本12.0.21005.1版本的运行时库。
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.VC120.CRT"
version="12.0.21005.1"
processorArchitecture="x86"
/>
</dependentAssembly>
</dependency>
做完上述的步骤之后,在虚拟机上模拟客户机器的状态。安装了低版本的vc120的运行时库,版本12.0.20617.1。
由于我们安装包里面是自带有12.0.21005.1版本的运行时库的,在安装时崩溃还是出现了,用process explorer看安装程序,在运行过程中还是调用了vc120 的12.0.20617.1运行时库。所以这里指定版本的manifest文件没有管用。那么继续google类似问题。找到了一篇博文http://mariusbancila.ro/blog/2010/03/24/visual-studio-2010-changes-for-vc-part-5/ ,在文章中得知也就是只是在vs2005和vs2008版本的运行时库会在系统 windows/WinSxS文件夹中创建相应版本运行时库的文件夹。而后续版本的运行时库不会使用这个文件夹来部署运行时库。所以这条路暂时是没有希望了。
那么换一个思路,动态库加载时候搜索路径的顺序。
由于安装包是用nsis脚本开发,在oninit回调函数中调用了我们的dll的一个函数,这时调用了vc120的运行时库。版本是12.0.20617.1。死结。由于运行时库已经加载进内存。系统不会再搜索其他版本的运行时库。所以只有在调用我们dll一个函数之前,先设置环境变量,调用SetEnvironmentVariable函数。
问题暂时先这么解决了。还有一个问题是明明我们开发的dll用的静态链编但是还是加载动态库。唉