程序是否在兼容模式下运行?

6

有没有C++ .NET函数可以调用,以便检测我的程序是否在兼容模式下运行?如果没有这样的函数,能否有人给我展示一个这样的代码?谢谢。

例如:

程序加载 检查兼容性模式 如果为真,则退出 否则运行


“兼容性”是什么意思? - Klaim
3
如果你禁用应用程序的兼容模式,各种用户都会讨厌你。为什么你要这样做呢?请保持翻译准确,并使内容更加通俗易懂,不添加任何额外信息。 - Billy ONeal
是的,禁用兼容模式相当具有限制性。 - Eton B.
3个回答

9

来自另一个论坛

在几次谷歌搜索失败后,我决定自己尝试一下。我发现每个可执行文件的兼容性设置都会被存储在Windows注册表中,就像我想的那样。

存储设置的关键是
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers

对于每个指定了其兼容性设置的应用程序,在该键下都存在一个值,其名称为可执行文件的路径,数据是一个包含兼容性设置的字符串。

指定兼容性设置的字符串中的关键字是:WIN95、WIN98、NT4SP5、WIN2000、256COLOR、640X480、DISABLETHEMES、DISABLECICERO。

如果要指定多个设置,则数据由上面的设置分别用空格隔开组成。前四个设置是互斥的,即只能指定其中之一(如果有的话)。我还没有测试指定多个操作系统的后果。

那么,回到解决您的问题。要检查一个可执行文件(假设为“C:\path\executable.exe”)是否设置为以256色模式运行,则在[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]键下会有一个名为“C:\path\executable.exe”的值(即使路径包含空格,也不要加引号),与该值关联的数据将包含字符串“256COLOR”。如果还设置为在Windows 98/ME下以兼容模式运行,则数据将为“WIN98 256COLOR”。

因此,方法很简单。测试是否存在具有可执行文件完整路径的值。如果不存在,则未指定任何兼容性设置。如果该值存在,则检索其数据并检查数据中是否存在“256COLOR”。相应地,“WIN95”、“WIN98”、“NT4SP5”或“WIN2000”的存在意味着该可执行文件被设置为在特定操作系统上运行的兼容模式。


1
很酷,但是在代码中,我该如何检查HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers是否有这些值之一?谢谢! - user409939
注册表和RegistryKey类。从概念上讲,与使用Windows API方式而不是.NET方式基本相同。 - Jon Hanna

4

获取从GetVersionEx返回的操作系统版本,将其与kernel32.dll上的文件版本进行比较。在应用程序兼容性模式下,GetVersionEx将始终返回正在“模拟”的操作系统版本。如果两个版本不同,则您处于应用程序兼容性模式。


2
上面的回答帮助我得到了一个“解决方案”,虽然可能不太优雅,但似乎能够工作。显然,在返回类型上可以更有创意一些。布尔值在这里不够用。我认为一个本地API会很好。
typedef VOID (NTAPI* TRtlGetNtVersionNumbers)(LPDWORD pdwMajorVersion, LPDWORD pdwMinorVersion, LPDWORD pdwBuildNumber);

bool IsRunningCompatMode()
{
    TRtlGetNtVersionNumbers RtlGetNtVersionNumbers = (TRtlGetNtVersionNumbers)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlGetNtVersionNumbers");

    assert(RtlGetNtVersionNumbers);

    if(RtlGetNtVersionNumbers)
    {
        OSVERSIONINFO osInfo = {0};
        osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
        GetVersionEx(&osInfo);

        DWORD dwMajorVersion;
        DWORD dwMinorVersion;
        DWORD dwBuildNumber;

        RtlGetNtVersionNumbers(&dwMajorVersion, &dwMinorVersion, &dwBuildNumber);

        dwBuildNumber &= 0x0000FFFF;

        if(osInfo.dwBuildNumber != dwBuildNumber)
        {
            return true;
        }
    }
    return false;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接