学无先后达者为师!
不忘初心,砥砺前行。

如何检测当前操作系统是否支持运行 .NET Core 3 / .NET 5 / .NET 6 应用?

虽然微软官方声称 .NET Core 3 / .NET 5 / .NET 6 应用支持在 Windows 7 及以上运行,但你不应该轻信。因为微软还在某个隐秘的角落里说明还应安装一枚 KB2533623 补丁。

直接判断补丁肯定是不靠谱的,因为还有其他几枚补丁(KB3063858、KB4457144)包含了这枚补丁。所以有没有什么靠谱写的判断方法呢?本文就来说说。

Windows 7 支持情况

KB2533623 补丁.NET Core 程序在 Windows 7 上需要 KB2533623 补丁才能运行本质上是需要它提供的这三个 Win32 函数:

  • SetDefaultDllDirectories
  • AddDllDirectory
  • RemoveDllDirectory

而我们可以通过 GetProcAddress 来判断这这些函数是否存在。由于这三个函数是一起添加到 kernel32.dll 里的,所以只需判断一个即可。

更多内容可参考 林德熙 的博客:探索 dotnet core 为何在 Windows7 系统需要补丁的原因

国内设备支持情况

根据本文即所述的判断方法,目前(2022年春节)国内环境对于 .NET Core 的支持情况如下:

国内 .NET Core 支持情况

▲ 国内 Windows 7 以上系统对 .NET Core 支持情况统计(数据已脱敏,因此只提供百分比)

其中,各系统支持情况为:

系统支持率
Windows 732.9%
Windows 7 SP197.1%
Windows 8/8.1/10/11100%

微软这些年一直在故意模糊 Windows 7 和 Windows 7 SP1 的界限,试图让不带 SP1 的 Windows 7 完全消失在任何微软的文档当中。然而,现实中的 Windows 7 可不会随着微软文档中相关文字的消失而消失。通过上表数据可以发现,不带 SP1 的 Windows 7 支持率低得可怜。好在 Windows 7(无 SP1)的设备数占所有 Windows 7 设备总数的 1.8%,不多也不少……还处于需要支持的数量级……

C# 版判断方法

判断所需的 Win32 函数:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "GetModuleHandleW", ExactSpelling = true, SetLastError = true)]
public static extern HMODULE GetModuleHandle([In][MarshalAs(UnmanagedType.LPWStr)] string lpModuleName);

[DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true, ThrowOnUnmappableChar = true)]
public static extern FARPROC GetProcAddress([In] HMODULE hModule, [In][MarshalAs(UnmanagedType.LPStr)] string lpProcName);

封装一个 C# 的调用,方便大家参考:

/// <summary>
/// 检查当前操作系统是否支持 .NET Core 运行时。
/// </summary>
/// <returns>支持则返回 true;否则返回 false。</returns>
public static bool CheckOSIsNetCoreSupported()
{
    var kernel32ModuleHandle = Win32.Kernel32.GetModuleHandle("kernel32");
    if (kernel32ModuleHandle != IntPtr.Zero)
    {
        // .NET Core 程序运行必要,但缺补丁的系统没有的三个函数:
        //  - SetDefaultDllDirectories
        //  - AddDllDirectory
        //  - RemoveDllDirectory
        var setDefaultDllDirectoriesProcAddress = Win32.Kernel32.GetProcAddress(kernel32ModuleHandle, "SetDefaultDllDirectories");
        return setDefaultDllDirectoriesProcAddress != IntPtr.Zero;
    }
    else
    {
        throw new InvalidOperationException("因为调用错误,无法获取 kernel32 的 ModuleName。");
    }
}

参考资料

赞(0) 打赏
未经允许不得转载:码农很忙 » 如何检测当前操作系统是否支持运行 .NET Core 3 / .NET 5 / .NET 6 应用?

评论 抢沙发

给作者买杯咖啡

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册