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); } } } }