如何解决R6034错误,实现在WIN7以上版本通过LoadLibrary加载msvcr90.dll等DLL
为什么VC编译的程序在不同系统上运行经常报错?
在XP(SP2 ?)以前,安装VC运行时库时,安装包只会将各种DLL释放到system32目录并注册相关信息到注册表,这样LoadLibrary时加载这些DLL也不会出错,因为对于应用程序来说,当前只有一个对应的运行时库被注册到系统中,不存在多个不同版本的问题,但也很容易造成兼容性问题,如使用VS2008编译的程序,在仅安装了VS2005运行时库的系统中可能会出现崩溃错误。
不同版本运行时库带来的冲突
假如一个VC2005编译的程序,一旦出现运行时库不匹配而导致运行错误,我们就需要安装匹配的VC2005运行时库到系统里就可以解决了.
但是如果问题那么容易解决就好了,不过对于这种问题如何解决,痛苦的也是微软的码农。
在上面VC2005程序问题的基础上,再扩展一下,假如同时又有一个VC2008编译的程序运行出现错误,这样我们又得安装VC2008的运行时库了,新的运行时库又会覆盖掉System32里的同名DLL,那么问题来了,原来的VC2005程序又无法运行了,崩溃!不可能每运行一次就安装一次运行时库把?
所以,微软在新的补丁中提供了一个叫Side-By-Side的模块,也就是简称SXS,该模块最初应该不是为了解决以上问题的,只是顺带而已,SXS应该是为了解决混乱的.NET Framework而设计的。但是不管怎样,有了SXS,就可以在系统中同时安装各种不同版本的运行时库也不会有冲突了。
既然系统中安装了不同版本的运行时库,那么程序怎么知道自己要使用的到底是VC2005还是VC2008的运行库呢?
微软如何设计SXS来解决不同运行环境所带来的兼容性问题的?
在XP sp3,以及Vista, WIN7,WIN8,WIN10 后,为了在系统中同时提供多种CPU平台和不同VS版本的运行时库来兼容不同的应用软件,微软做了大概下面3个改进,
1)PE文件自带依赖库签名信息
2)在C:\Windows\WinSxS中存放各种不同版本的运行时库
3)有了上面的2个改进,剩下的无非就是系统运行EXE文件或者加载DLL时,如何根据依赖库签名信息来正确加载相应的运行时库了。
以上就是系统的Side-By-Side(SXS)组件设计时所要实现的大体目标和功能了。
程序开发中如何让SXS的识别不同版本依赖库?
在VS开发时,可在工具中设置manifest来指定当前程序的依赖库签名信息(运行时库名称,版本,如win32 x86 版本号 等等),manifest可以嵌入到资源中,也可以放在本地的xml格式的文本文件,目前最标准的也是VS开发工具默认做法,就是将运行时库通过导入表静态链接到PE文件(EXE或DLL),同时将manifest嵌入到PE文件的资源里,资源号是RT_MANIFEST(24),再交给系统的PE加载器去自动加载对应的运行时库。
虽然本文是说MSVCR90.DLL,但原理上是可以适用于各种各样的运行时库的。
#include <string>
#include <windows.h>
#if !defined(_UNICODE) && !defined(UNICODE)
#define tstring std::string
#else
#define tstring std::wstring
#endif
#define TSTRING tstring
void LoadMSVCRT90()
{
TSTRING sDllName = _T("");
HMODULE hLib = NULL;
ACTCTX aActCtx = { 0 };
HANDLE hCtx = NULL;
ULONG_PTR lpCookie = 0L;
memset(&aActCtx, 0, sizeof(aActCtx));
aActCtx.cbSize = sizeof(aActCtx);
aActCtx.lpSource = _T("MSVCRT.manifest");
hCtx = ::CreateActCtx(&aActCtx);
if (hCtx == INVALID_HANDLE_VALUE)
{
return;
}
::ActivateActCtx(hCtx, &lpCookie);
sDllName = _T("MSVCR90.DLL");
hLib = ::LoadLibrary(sDllName.c_str());
if (!hLib || hLib == INVALID_HANDLE_VALUE)
{
return;
}
::DeactivateActCtx(0, lpCookie);
::ReleaseActCtx(hCtx);
}
/*************************************************************************************************
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</trustInfo>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
</dependentAssembly>
</dependency>
</assembly>
*************************************************************************************************/