Windows从Vista之后,新增了一个应用程序的兼容模式。比如程序在XP系统下面可以正常运行,但是系统升级到Win7之后,调用的一个XP的系统接口在Win7系统里不存在或者接口行为或者参数意义发生了改变,这样程序运行的时候就会发生崩溃或者异常。兼容模式就是让程序不变的情况下,操作系统自己去兼容程序的API调用。
我们在Win7上面右键菜单查看属性,选择兼容性,可以看到如下图所示:

选择兼容模式,就可以让应用程序兼容所选定的操作系统运行。
比如我们选择兼容Windows XP(Service Pack 3)来运行程序,这时候操作系统就会在注册表的HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers位置建立一个以程序路径为key,值为WINXPSP3的字符串,如下图所示:

在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers里面也有同样的设置,它是对所有用户都生效。
此外,程序的环境变量里面也多了一个”__COMPAT_LAYER=WinXPSp3”,如下图所示:

不同的兼容模式,其值不一样的,可以参加这篇文档的最底部https://msdn.microsoft.com/en-us/windows/compatibility/pca-scenarios-for-windows-8,下面是一些常见的值:
Mode |
Description |
Windows7RTM |
This mode emulates common Windows 7 behavior including the operating system version number 6.1 |
WindowsVistaSP2 |
This mode emulates common Windows 7 behavior including the operating system version number 6.1 |
WindowsXPSp3 |
This mode emulates common Windows XP SP3 behavior including the operating system version number 5.1. This also includes the RUNASHIGHEST mode |
RUNASHIGHEST |
This mode prompts the user to run the app with the highest available privilege. Users with administrative privileges will see a UAC elevation prompt for the app |
RUNASADMIN |
This mode always prompts the user to run the app with administrative privileges; apps with this mode will always get the UAC elevation prompt |
ELEVATECREATEPROCESS |
This mode makes child processes of the main app run with administrative privileges; the child processes will get a UAC elevation dialog |
PINDLL |
This mode forces a DLL to be in memory for an app even if the app unloads the DLL |
DISABLEUSERCALLBACKEXCEPTION |
This mode intercepts user call back exceptions and allows the app to continue on without having to handle the exception |
VIRTUALIZEDELETE |
This mode intercepts delete operations on protected files and prevents apps from failing due to unhandled exceptions from the delete operation |
WRPMITIGATION |
This mode returns success when an app tries to write, modify, or delete Windows protected files or registry entries (without actually completing the operation) |
DXMAXIMIZEDWINDOWEDMODE |
This mode identifies apps that go into full screen mode and redirects them into a maximized Window mode |
HIGHDPIAWARE |
This mode lets the rest of Windows know that the app is High DPI aware, and helps proper rendering of UI elements, text, font, etc. |
所以,通过代码的方法以兼容模式运行程序,有两种办法:
- 在注册表的HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers位置建立一个以程序路径为key,值为WINXPSP3的字符串。这个是持久化的办法,只有注册表里面存在这个值,程序就一直以兼容模式运行。
- 父进程设置环境变量”__COMPAT_LAYER=WinXPSp3”,然后启动子进程,那么子进程就是以兼容模式运行。这个是非持久化的让程序以兼容模式运行。
Windows是如何实现兼容模式的呢。其实很简单,当程序设置了以兼容模式运行的标志之后,操作系统会为程序加载C:\Windows\AppPatch目录下面的AcGenral.dll、AcLayers.dll、AcXtrnal.dll,这个Dll会Hook住程序的系统API调用,返回程序兼容的结果。如下面:
AcLayers.dll!NS_ElevateCreateProcess::APIHook_CreateProcessW+0x77
chrome.dll!base::LaunchProcess+0x560
chrome.dll!base::LaunchProcess+0x34
chrome.dll!content::StartSandboxedProcess+0x6fd
程序在兼容模式里调用CreateProcessW,实际上调用的是cLayers.dll!NS_ElevateCreateProcess::APIHook_CreateProcessW
说到这里,这就是Windows的Application Compatibility Shims技术。Shim是微软系统中一个小型函数库,用于透明地拦截API调用,修改传递的参数、自身处理操作、或把操作重定向到其他地方。Shim主要用于解决遗留应用程序在新版Windows系统上的兼容性问题。相关介绍见https://technet.microsoft.com/en-us/library/dd837644(v=ws.10).aspx、http://www.freebuf.com/news/48878.html。