在.NET Core中确定操作系统

185

如何确定我的.NET Core应用程序正在运行的操作系统?以前我可以使用Environment.OSVersion

现在要确定我的应用程序是否在Mac或Windows上运行,应该采用什么方法?


请查看此链接:https://dev59.com/Kl4b5IYBdhLWcg3w9Fur#28664021 - Kovpaev Alexey
不是我想要的答案,但我自己找到了。 - dknaack
Environment.OSVersion 在 .NET Core 2.0+ 中可用。 - undefined
3个回答

289

方法

System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform()

可能的争论

OSPlatform.Windows
OSPlatform.OSX
OSPlatform.Linux

示例

bool isWindows = System.Runtime.InteropServices.RuntimeInformation
                                               .IsOSPlatform(OSPlatform.Windows);

更新

感谢 Oleksii Vynnychenko 的评论

您可以使用以下方法获得操作系统名称和版本号的字符串

var osNameAndVersion = System.Runtime.InteropServices.RuntimeInformation.OSDescription;

例如,osNameAndVersion 将是 Microsoft Windows 10.0.10586


6
你可以添加以下内容以获取更多关于操作系统的信息:在该包中,还有另一个属性System.Runtime.InteropServices.RuntimeInformation.OSDescription,它返回关于操作系统的描述和版本等信息。 - Oleksii Vynnychenko
24
尽管我不喜欢这个答案,但我还是要点赞。为什么不能为了一致性而实现 System.Environment.OSVersion.Platform 呢? - leppie
2
请注意,常量并未表示所有支持的操作系统。可以通过使用 IsOSPlatform(OSPlatform.Create("FreeBSD")) 探测其他操作系统,无论它们现在是否受支持或将来可能添加。然而,关于传递什么字符串的安全方法不是很清楚(例如,大小写是否敏感,或者 "bsd" 是否匹配 "FreeBSD""NetBSD"?)。请参见有关此功能的讨论此处 - NightOwl888
5
注意!RuntimeInformation.IsOSPlatform 不是检查当前操作系统,而是检查构建配置目标。证据:https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/OperatingSystem.cs#L91请参考此答案 https://dev59.com/aVkT5IYBdhLWcg3wStzQ#66618677 - Alex from Jitbit

51

查看 System.OperatingSystem 类,它拥有每个 OS 的静态方法,例如 IsMacOS()IsWindows()IsIOS() 等等。这些方法从 .NET 5 开始可用。

这使其成为一个不错的选择,因为这些方法的实现使用预处理指令,在编译时将返回值修正为针对每个目标操作系统的常量 true/false。没有运行时探测或调用。

以下是 OperatingSystem 中一个这样的方法的摘录:

        /// <summary>
        /// Indicates whether the current application is running on Linux.
        /// </summary>
        [NonVersionable]
        public static bool IsLinux() =>
#if TARGET_LINUX && !TARGET_ANDROID
            true;
#else
            false;
#endif

6
这应该是最佳答案。 - Alex from Jitbit
1
只有当您的目标是 .NET 5 或更高版本时,该 API 才可用。不幸的是,该 API 在 .NET Core 或任何 .NET 标准中都不存在。 - lethek

50

System.Environment.OSVersion.Platform 可以在完整的.NET Framework和Mono中使用,但:

  • 在Mono下,几乎从未成功过Mac OS X检测
  • .NET Core中没有实现

System.Runtime.InteropServices.RuntimeInformation 可以在.NET Core中使用,但:

  • 在完整的.NET Framework和Mono中没有实现
  • 它并不执行运行时的平台检测,而是使用硬编码信息
    (请参见corefx问题#3032获取更多详细信息)

您可以调用特定于平台的非托管函数,例如uname(),但:

  • 它可能会在未知平台上导致分段错误
  • 在某些项目中不允许

因此,我建议的解决方案(参见下面的代码)一开始可能看起来很傻,但:

  • 它使用100%托管代码
  • 它适用于.NET,Mono和.NET Core
  • Pkcs11Interop库中到目前为止它运行得很好
string windir = Environment.GetEnvironmentVariable("windir");
if (!string.IsNullOrEmpty(windir) && windir.Contains(@"\") && Directory.Exists(windir))
{
    _isWindows = true;
}
else if (File.Exists(@"/proc/sys/kernel/ostype"))
{
    string osType = File.ReadAllText(@"/proc/sys/kernel/ostype");
    if (osType.StartsWith("Linux", StringComparison.OrdinalIgnoreCase))
    {
        // Note: Android gets here too
        _isLinux = true;
    }
    else
    {
        throw new UnsupportedPlatformException(osType);
    }
}
else if (File.Exists(@"/System/Library/CoreServices/SystemVersion.plist"))
{
    // Note: iOS gets here too
    _isMacOsX = true;
}
else
{
    throw new UnsupportedPlatformException();
}

1
感谢您的努力。希望未来能有一些一致性。 - leppie
8
现在(自去年11月起),System.Runtime.InteropServices.RuntimeInformation 在完整的 .net 中应该可以正常工作,因此这似乎是现在被接受的“正确”方式。不确定 Mono 是否也是如此,但因为他们现在直接从 .net 中获取一些代码,所以在那里它能否正常工作只是时间问题,如果还没有的话。 - GrandOpener
3
Path.DirectorySeparatorChar 可以用来确定是 Windows 还是 *nix 机器。 - kiran
InteropServices非常奇怪。在VStudio和Rider中,有时会出现“在此上下文中未知”或编译错误的情况。对于这种失败的原因一无所知... - Slesa

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