using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
#if SMAPI_FOR_WINDOWS
using System.Management;
#endif
using System.Runtime.InteropServices;
namespace StardewModdingAPI.Toolkit.Utilities
{
/// Provides methods for fetching environment information.
public static class EnvironmentUtility
{
/*********
** Fields
*********/
/// Get the OS name from the system uname command.
/// The buffer to fill with the resulting string.
[DllImport("libc")]
static extern int uname(IntPtr buffer);
/*********
** Public methods
*********/
/// Detect the current OS.
public static Platform DetectPlatform()
{
switch (Environment.OSVersion.Platform)
{
case PlatformID.MacOSX:
return Platform.Mac;
case PlatformID.Unix:
return EnvironmentUtility.IsRunningMac()
? Platform.Mac
: Platform.Linux;
default:
return Platform.Windows;
}
}
/// Get the human-readable OS name and version.
/// The current platform.
[SuppressMessage("ReSharper", "EmptyGeneralCatchClause", Justification = "Error suppressed deliberately to fallback to default behaviour.")]
public static string GetFriendlyPlatformName(Platform platform)
{
#if SMAPI_FOR_WINDOWS
try
{
return new ManagementObjectSearcher("SELECT Caption FROM Win32_OperatingSystem")
.Get()
.Cast()
.Select(entry => entry.GetPropertyValue("Caption").ToString())
.FirstOrDefault();
}
catch { }
#endif
return (platform == Platform.Mac ? "MacOS " : "") + Environment.OSVersion;
}
/// Get the name of the Stardew Valley executable.
/// The current platform.
public static string GetExecutableName(Platform platform)
{
return platform == Platform.Windows
? "Stardew Valley.exe"
: "StardewValley.exe";
}
/// Get whether the platform uses Mono.
/// The current platform.
public static bool IsMono(this Platform platform)
{
return platform == Platform.Linux || platform == Platform.Mac;
}
/*********
** Private methods
*********/
/// Detect whether the code is running on Mac.
///
/// This code is derived from the Mono project (see System.Windows.Forms/System.Windows.Forms/XplatUI.cs). It detects Mac by calling the
/// uname system command and checking the response, which is always 'Darwin' for MacOS.
///
private static bool IsRunningMac()
{
IntPtr buffer = IntPtr.Zero;
try
{
buffer = Marshal.AllocHGlobal(8192);
if (EnvironmentUtility.uname(buffer) == 0)
{
string os = Marshal.PtrToStringAnsi(buffer);
return os == "Darwin";
}
return false;
}
catch
{
return false; // default to Linux
}
finally
{
if (buffer != IntPtr.Zero)
Marshal.FreeHGlobal(buffer);
}
}
}
}