How to check the OS version at runtime, e.g. on Windows or Linux, without using a conditional compilation statement
Asked Answered
T

12

132

How do I determine what platform my C# code is running on? for example whether it is running on Linux or windows so that I can execute different code at runtime.

I have a C# Windows application that I want to build to target Windows and Linux platforms.

So far I have created two project files pointing to the same set of source code files. I then use a conditional compilation statement one of the projects called LINUX.

Where there are difference in the actual code I use conditional statements using the conditional compilation statement, for example,

#if (LINUX)
    ' Do something
#endif

Is there a better way of doing this? I don't really want to have two project files.

Transilluminate answered 25/2, 2011 at 12:1 Comment(0)
M
87

[Editor's Note: This answer was applicable before .NET 4.7.1, or before the Windows Compatibility Pack for .NET Core was released. The current best answer is Alex Sanséau's to Stack Overflow question How to check the OS version at runtime, e.g. on Windows or Linux, without using a conditional compilation statement.]

You can detect the execution platform using System.Environment.OSVersion.Platform:

public static bool IsLinux
{
    get
    {
        int p = (int) Environment.OSVersion.Platform;
        return (p == 4) || (p == 6) || (p == 128);
    }
}

From the Mono FAQ:

How to detect the execution platform

The execution platform can be detected by using the System.Environment.OSVersion.Platform value. However correctly detecting Unix platforms, in every cases, requires a little more work. The first versions of the framework (1.0 and 1.1) didn't include any PlatformID value for Unix, so Mono used the value 128. The newer framework 2.0 added Unix to the PlatformID enum but, sadly, with a different value: 4 and newer versions of .NET distinguished between Unix and macOS, introducing yet another value 6 for macOS.

This means that in order to detect properly code running on Unix platforms you must check the three values (4, 6 and 128). This ensure that the detection code will work as expected when executed on Mono CLR 1.x runtime and with both Mono and Microsoft CLR 2.x runtimes.

Modifier answered 25/2, 2011 at 12:4 Comment(3)
So we probably shouldnt use 6 for IsLinux, then ;)Kamasutra
That was 2011, today the correct answer is RuntimeInformation.IsOSPlatform(), as suggested by @AlexAmaris
Shorter: public static bool IsLinux => (int) Environment.OSVersion.Platform is 4 or 6 or 128;Evetteevey
N
198

I found this recommendation on one of Microsoft's blogs:

We recommend you to use RuntimeInformation.IsOSPlatform() for platform checks.

Reference: Announcing the Windows Compatibility Pack for .NET Core

IsOSPlatform() takes an argument of types OSPlatform which has three values by default: Windows, Linux and OSX. It can be used as follow:

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
  // Do something
}

The API is part of .NET Standard 2.0, and therefore available in .NET Core 2.0 and .NET Framework 4.7.1.

Neuropath answered 20/11, 2017 at 10:53 Comment(4)
nuget.org/packages/… for many more platforms.Kaitlynkaitlynn
Don't forget using System.Runtime.InteropServices;Bobbobb
There is also a fourth option now, FreeBSD.Inductor
Worked for .NET 5. :)Fivefold
M
87

[Editor's Note: This answer was applicable before .NET 4.7.1, or before the Windows Compatibility Pack for .NET Core was released. The current best answer is Alex Sanséau's to Stack Overflow question How to check the OS version at runtime, e.g. on Windows or Linux, without using a conditional compilation statement.]

You can detect the execution platform using System.Environment.OSVersion.Platform:

public static bool IsLinux
{
    get
    {
        int p = (int) Environment.OSVersion.Platform;
        return (p == 4) || (p == 6) || (p == 128);
    }
}

From the Mono FAQ:

How to detect the execution platform

The execution platform can be detected by using the System.Environment.OSVersion.Platform value. However correctly detecting Unix platforms, in every cases, requires a little more work. The first versions of the framework (1.0 and 1.1) didn't include any PlatformID value for Unix, so Mono used the value 128. The newer framework 2.0 added Unix to the PlatformID enum but, sadly, with a different value: 4 and newer versions of .NET distinguished between Unix and macOS, introducing yet another value 6 for macOS.

This means that in order to detect properly code running on Unix platforms you must check the three values (4, 6 and 128). This ensure that the detection code will work as expected when executed on Mono CLR 1.x runtime and with both Mono and Microsoft CLR 2.x runtimes.

Modifier answered 25/2, 2011 at 12:4 Comment(3)
So we probably shouldnt use 6 for IsLinux, then ;)Kamasutra
That was 2011, today the correct answer is RuntimeInformation.IsOSPlatform(), as suggested by @AlexAmaris
Shorter: public static bool IsLinux => (int) Environment.OSVersion.Platform is 4 or 6 or 128;Evetteevey
R
38

.NET 5+ has the OperatingSystem class, so now you can just:

if (OperatingSystem.IsWindows())
    DoSomething();
Rogerson answered 30/6, 2022 at 12:9 Comment(1)
Important to note that this solution is only for .NET Core.Anticlockwise
T
19

There isn't any such method, but you can use this method that checks it conditionally:

    public static OSPlatform GetOperatingSystem()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            return OSPlatform.OSX;
        }

        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            return OSPlatform.Linux;
        }

        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            return OSPlatform.Windows;
        }

        throw new Exception("Cannot determine operating system!");
    }
Tarnetgaronne answered 12/12, 2019 at 5:56 Comment(0)
S
12

Use:

System.Environment.OSVersion
Saintly answered 25/2, 2011 at 12:4 Comment(0)
S
3

You can use System.Environment.OSVersion to check what kind of platform you're on at runtime.

Shemikashemite answered 25/2, 2011 at 12:5 Comment(1)
No, you can't, because it returns true for Unix/Linux if you're on Mac, and true for Mac if you're on Unix/Linux...Sepalous
M
3

To expand on other answers, in cases where a Linux and Windows implementation of a feature are not compatible (that is, require references to libraries only available for a specific platform), you can also use an interface and have two separate assemblies, one written and compiled on each platform, with a type that implements this interface.

Then, based on the check, use Assembly.Load() to load only the right assembly (and its platform-specific dependency), reflection to find your type in the assembly, and Activator.CreateInstance() to get an instance of the type that you can then work with normally.

Monogamy answered 20/12, 2011 at 3:41 Comment(1)
UpVote to you, all other answers are runtime checks which means publish folder would contains all dependencies - like windows.publish would contain linux dependencies and so on. Why there's no way to do that during compilation ?Jipijapa
N
1
OperatingSystem os = new OperatingSystem(System.Environment.OSVersion.Platform, new Version());
Console.WriteLine(os.ToString());
Narcotism answered 30/8, 2021 at 17:8 Comment(3)
Please provide explanation about your code that how can this solve the problem.Spavined
It just simply return you a string, the name of the operating system. I don't think so any explanation is needed so far.Narcotism
the Vesrion() class represents the assembly version of your CLRNarcotism
S
1

Built-in static method: System.Runtime.Serialization.OperatingSystem.IsLinux().

San answered 15/9, 2021 at 9:37 Comment(0)
F
0

One more option is to use Process to call a shell script to get the uname, as follows:

Process p = new Process {
  StartInfo = {
    UseShellExecute        = false,
    RedirectStandardOutput = true,
    FileName               = "uname",
    Arguments              = "-s"
  }
};
p.Start();
string uname = p.StandardOutput.ReadToEnd().Trim();

if (uname == "Darwin") {
  // OS X
} else {
  // ...
}
Froggy answered 26/3, 2019 at 4:41 Comment(1)
This does not work for Windows.Cryotherapy
A
0

I do this which works across:

netstandard2.0, netstandard2.1, net48, net6.0, net7.0

public static class EnumExtensions
{
    public static bool Running(this OSPlatform val)
    {
        return  RuntimeInformation.IsOSPlatform(val);
    }
}

To use it:

if (OSPlatform.Windows.Running())
    DoSomething();
else if (OSPlatform.OSX.Running())
    DoSomethingElse();
Anticlockwise answered 7/12, 2023 at 18:30 Comment(0)
M
-2

With the help of TimeZoneConverter libraryable to map the google timezone with the windows time zone. This library has support for windows and Linux and most of the systems.

using TimeZoneConverter;
//Convert Google's Time zone Id into Standard Time Zone name using TimeZoneConvertor library's method named 'GetTimeZoneInfo'
Input : Asia/Hong_Kong 
Output : China Standard Time
TimeZoneInfo tz = TZConvert.GetTimeZoneInfo(timeZoneId);
Michaels answered 31/3, 2023 at 10:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.