Применение к сессии, USE заменён на checkbox
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using Sms.Environment;
|
||||
|
||||
namespace Sms.Environment.Linux;
|
||||
@@ -5,6 +6,7 @@ namespace Sms.Environment.Linux;
|
||||
public sealed class LinuxEnvironmentVariableStore : IEnvironmentVariableStore
|
||||
{
|
||||
private const string ManagedFileName = "99-sms-task-two.conf";
|
||||
private const int SystemctlBatchSize = 32;
|
||||
|
||||
private readonly string _managedFilePath;
|
||||
private readonly string _environmentDirectory;
|
||||
@@ -119,6 +121,7 @@ public sealed class LinuxEnvironmentVariableStore : IEnvironmentVariableStore
|
||||
}
|
||||
|
||||
System.Environment.SetEnvironmentVariable(name, null);
|
||||
TryRunSystemctl(["--user", "unset-environment", name], out _);
|
||||
}
|
||||
catch (Exception ex) when (ex is UnauthorizedAccessException or IOException)
|
||||
{
|
||||
@@ -128,6 +131,142 @@ public sealed class LinuxEnvironmentVariableStore : IEnvironmentVariableStore
|
||||
}
|
||||
}
|
||||
|
||||
public EnvironmentReloadResult ReloadEnvironment()
|
||||
{
|
||||
var variables = GetUserPersistedEnvironment();
|
||||
ApplyToCurrentProcess(variables);
|
||||
|
||||
if (variables.Count == 0)
|
||||
{
|
||||
return new EnvironmentReloadResult
|
||||
{
|
||||
Success = true,
|
||||
Message = "Пользовательских переменных для применения нет.",
|
||||
};
|
||||
}
|
||||
|
||||
var messages = new List<string>();
|
||||
if (TryApplyViaSystemctl(variables, out var systemctlError))
|
||||
{
|
||||
messages.Add("systemd user manager обновлён (systemctl --user set-environment).");
|
||||
}
|
||||
else if (systemctlError is not null)
|
||||
{
|
||||
messages.Add($"systemctl: {systemctlError}");
|
||||
}
|
||||
|
||||
if (TryApplyViaDbusUpdateEnvironment(variables, out var dbusError))
|
||||
{
|
||||
messages.Add("D-Bus session обновлён (dbus-update-environment).");
|
||||
}
|
||||
else if (dbusError is not null)
|
||||
{
|
||||
messages.Add($"dbus-update-environment: {dbusError}");
|
||||
}
|
||||
|
||||
var processApplied = messages.Count > 0 || variables.Count > 0;
|
||||
return new EnvironmentReloadResult
|
||||
{
|
||||
Success = processApplied,
|
||||
Message = processApplied
|
||||
? $"Применено {variables.Count} переменных к текущему процессу. {string.Join(' ', messages)}"
|
||||
: "Не удалось применить переменные к сессии.",
|
||||
};
|
||||
}
|
||||
|
||||
private static void ApplyToCurrentProcess(IReadOnlyDictionary<string, string> variables)
|
||||
{
|
||||
foreach (var pair in variables)
|
||||
{
|
||||
System.Environment.SetEnvironmentVariable(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryApplyViaSystemctl(
|
||||
IReadOnlyDictionary<string, string> variables,
|
||||
out string? errorMessage)
|
||||
{
|
||||
errorMessage = null;
|
||||
var pairs = variables.ToList();
|
||||
for (var offset = 0; offset < pairs.Count; offset += SystemctlBatchSize)
|
||||
{
|
||||
var arguments = new List<string> { "--user", "set-environment" };
|
||||
foreach (var pair in pairs.Skip(offset).Take(SystemctlBatchSize))
|
||||
{
|
||||
arguments.Add($"{pair.Key}={pair.Value}");
|
||||
}
|
||||
|
||||
if (!TryRunSystemctl(arguments, out errorMessage))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryApplyViaDbusUpdateEnvironment(
|
||||
IReadOnlyDictionary<string, string> variables,
|
||||
out string? errorMessage)
|
||||
{
|
||||
var arguments = new List<string>();
|
||||
foreach (var pair in variables)
|
||||
{
|
||||
arguments.Add($"{pair.Key}={pair.Value}");
|
||||
}
|
||||
|
||||
return TryRunCommand("dbus-update-environment", arguments, out errorMessage);
|
||||
}
|
||||
|
||||
private static bool TryRunSystemctl(IReadOnlyList<string> arguments, out string? errorMessage) =>
|
||||
TryRunCommand("systemctl", arguments, out errorMessage);
|
||||
|
||||
private static bool TryRunCommand(
|
||||
string fileName,
|
||||
IReadOnlyList<string> arguments,
|
||||
out string? errorMessage)
|
||||
{
|
||||
errorMessage = null;
|
||||
try
|
||||
{
|
||||
var startInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = fileName,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
UseShellExecute = false,
|
||||
};
|
||||
foreach (var argument in arguments)
|
||||
{
|
||||
startInfo.ArgumentList.Add(argument);
|
||||
}
|
||||
|
||||
using var process = Process.Start(startInfo);
|
||||
if (process is null)
|
||||
{
|
||||
errorMessage = "не удалось запустить процесс";
|
||||
return false;
|
||||
}
|
||||
|
||||
var stderr = process.StandardError.ReadToEnd();
|
||||
process.WaitForExit(5000);
|
||||
if (process.ExitCode == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
errorMessage = string.IsNullOrWhiteSpace(stderr)
|
||||
? $"код выхода {process.ExitCode}"
|
||||
: stderr.Trim();
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
errorMessage = ex.Message;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, string> LoadManagedFile()
|
||||
{
|
||||
if (!File.Exists(_managedFilePath))
|
||||
|
||||
Reference in New Issue
Block a user