using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace SyncEngine.Configuration { /// Parses and loads key=value pairs from a .env file beside the executable. public static class EnvSettings { public static EnvLoadResult LoadFromStandardLocations() { var result = new EnvLoadResult(); var exeDir = ExeDirectory(); var candidates = new List { Path.Combine(exeDir, ".env"), Path.GetFullPath(Path.Combine(exeDir, "..", "..", "..", "..", ".env")) }; foreach (var path in candidates.Distinct(StringComparer.OrdinalIgnoreCase)) { if (!File.Exists(path)) { continue; } Load(path); result.LoadedPaths.Add(path); break; } result.Found = result.LoadedPaths.Count > 0; return result; } public static void Load(string envPath) { if (!File.Exists(envPath)) { return; } foreach (var line in File.ReadAllLines(envPath)) { var trimmed = line.Trim(); if (trimmed.Length == 0 || trimmed.StartsWith("#", StringComparison.Ordinal)) { continue; } var eq = trimmed.IndexOf('='); if (eq <= 0) { continue; } var key = trimmed.Substring(0, eq).Trim(); var value = trimmed.Substring(eq + 1).Trim(); if (value.Length >= 2 && ((value.StartsWith("\"", StringComparison.Ordinal) && value.EndsWith("\"", StringComparison.Ordinal)) || (value.StartsWith("'", StringComparison.Ordinal) && value.EndsWith("'", StringComparison.Ordinal)))) { value = value.Substring(1, value.Length - 2); } Environment.SetEnvironmentVariable(key, value, EnvironmentVariableTarget.Process); } } public static string Get(string key, string defaultValue = "") { return Environment.GetEnvironmentVariable(key) ?? defaultValue; } public static bool GetBool(string key, bool defaultValue) { var raw = Get(key, null); if (string.IsNullOrWhiteSpace(raw)) { return defaultValue; } return raw.Equals("true", StringComparison.OrdinalIgnoreCase) || raw.Equals("1", StringComparison.OrdinalIgnoreCase) || raw.Equals("yes", StringComparison.OrdinalIgnoreCase); } public static int GetInt(string key, int defaultValue) { var raw = Get(key, null); int value; return int.TryParse(raw, out value) ? value : defaultValue; } public static string ResolvePath(string path) { if (string.IsNullOrWhiteSpace(path)) { return path; } return Path.IsPathRooted(path) ? path : Path.GetFullPath(path); } public static string ExeDirectory() { return AppDomain.CurrentDomain.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } } public sealed class EnvLoadResult { public bool Found { get; set; } public IList LoadedPaths { get; set; } = new List(); } }