Files
sms-task-two/src/Sms.Environment.Windows/WindowsEnvironmentVariableStore.cs

98 lines
3.1 KiB
C#

using System.Runtime.InteropServices;
using Sms.Environment;
namespace Sms.Environment.Windows;
public sealed class WindowsEnvironmentVariableStore : IEnvironmentVariableStore
{
private const int HWND_BROADCAST = 0xffff;
private const int WM_SETTINGCHANGE = 0x001A;
public string? Get(string name) =>
System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.User)
?? System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
public void Set(string name, string value)
{
System.Environment.SetEnvironmentVariable(name, value, EnvironmentVariableTarget.User);
System.Environment.SetEnvironmentVariable(name, value, EnvironmentVariableTarget.Process);
BroadcastEnvironmentChange();
}
public bool Exists(string name) => Get(name) is not null;
public IReadOnlyDictionary<string, string> GetAll(IEnumerable<string> names)
{
var result = new Dictionary<string, string>(StringComparer.Ordinal);
foreach (var name in names)
{
var value = Get(name);
if (value is not null)
{
result[name] = value;
}
}
return result;
}
public IReadOnlyDictionary<string, string> GetProcessEnvironment() =>
ToDictionary(System.Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process));
public IReadOnlyDictionary<string, string> GetUserPersistedEnvironment() =>
ToDictionary(System.Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User));
public bool IsPersistedInUserStore(string name) =>
System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.User) is not null;
public void RemoveFromUserStore(string name)
{
System.Environment.SetEnvironmentVariable(name, null, EnvironmentVariableTarget.User);
System.Environment.SetEnvironmentVariable(name, null, EnvironmentVariableTarget.Process);
BroadcastEnvironmentChange();
}
private static Dictionary<string, string> ToDictionary(System.Collections.IDictionary source)
{
var result = new Dictionary<string, string>(StringComparer.Ordinal);
foreach (string key in source.Keys)
{
result[key] = source[key]?.ToString() ?? string.Empty;
}
return result;
}
private static void BroadcastEnvironmentChange()
{
try
{
_ = NativeMethods.SendMessageTimeout(
HWND_BROADCAST,
WM_SETTINGCHANGE,
IntPtr.Zero,
"Environment",
0,
1000,
out _);
}
catch
{
// Non-critical: new processes still see updated registry values.
}
}
private static class NativeMethods
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SendMessageTimeout(
int hWnd,
int msg,
IntPtr wParam,
string lParam,
int fuFlags,
int uTimeout,
out IntPtr lpdwResult);
}
}