Update environment variables changed (#12689)

This commit is contained in:
Derek Christensen 2021-08-18 09:43:24 -06:00 committed by GitHub
parent 31a5d49246
commit e87e06bae6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 4 deletions

View File

@ -0,0 +1,98 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using Microsoft.Win32.SafeHandles;
using Wox.Plugin.Logger;
namespace PowerLauncher.Helper
{
public static class EnvironmentHelper
{
private const string EnvironmentChangeType = "Environment";
private const string Username = "USERNAME";
private const string ProcessorArchitecture = "PROCESSOR_ARCHITECTURE";
private const string Path = "PATH";
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "Params are required for delegate signature requirements.")]
public static IntPtr ProcessWindowMessages(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
{
switch ((WM)msg)
{
case WM.SETTINGCHANGE:
string changeType = Marshal.PtrToStringUni(lparam);
if (changeType == EnvironmentChangeType)
{
Log.Info("Reload environment", typeof(EnvironmentHelper));
UpdateEnvironment();
handled = true;
}
break;
}
return IntPtr.Zero;
}
private static void UpdateEnvironment()
{
// Username and process architecture are set by the machine vars, this
// may lead to incorrect values so save off the current values to restore.
string originalUsername = Environment.GetEnvironmentVariable(Username, EnvironmentVariableTarget.Process);
string originalArch = Environment.GetEnvironmentVariable(ProcessorArchitecture, EnvironmentVariableTarget.Process);
var environment = new Dictionary<string, string>();
MergeTargetEnvironmentVariables(environment, EnvironmentVariableTarget.Process);
MergeTargetEnvironmentVariables(environment, EnvironmentVariableTarget.Machine);
if (!IsRunningAsSystem())
{
MergeTargetEnvironmentVariables(environment, EnvironmentVariableTarget.User);
// Special handling for PATH - merge Machine & User instead of override
var pathTargets = new[] { EnvironmentVariableTarget.Machine, EnvironmentVariableTarget.User };
var paths = pathTargets
.Select(t => Environment.GetEnvironmentVariable(Path, t))
.Where(e => e != null)
.SelectMany(e => e.Split(';', StringSplitOptions.RemoveEmptyEntries))
.Distinct();
environment[Path] = string.Join(';', paths);
}
environment[Username] = originalUsername;
environment[ProcessorArchitecture] = originalArch;
foreach (KeyValuePair<string, string> kv in environment)
{
Environment.SetEnvironmentVariable(kv.Key, kv.Value, EnvironmentVariableTarget.Process);
}
}
private static void MergeTargetEnvironmentVariables(
Dictionary<string, string> environment, EnvironmentVariableTarget target)
{
IDictionary variables = Environment.GetEnvironmentVariables(target);
foreach (DictionaryEntry entry in variables)
{
environment[(string)entry.Key] = (string)entry.Value;
}
}
private static bool IsRunningAsSystem()
{
using (var identity = WindowsIdentity.GetCurrent())
{
return identity.IsSystem;
}
}
}
}

View File

@ -7,6 +7,7 @@ using System.ComponentModel;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security; using System.Security;
using System.Text; using System.Text;
using Microsoft.Win32.SafeHandles;
using static PowerLauncher.Helper.WindowsInteropHelper; using static PowerLauncher.Helper.WindowsInteropHelper;
// http://blogs.microsoft.co.il/arik/2010/05/28/wpf-single-instance-application/ // http://blogs.microsoft.co.il/arik/2010/05/28/wpf-single-instance-application/
@ -108,6 +109,7 @@ namespace PowerLauncher.Helper
ERASEBKGND = 0x0014, ERASEBKGND = 0x0014,
SYSCOLORCHANGE = 0x0015, SYSCOLORCHANGE = 0x0015,
SHOWWINDOW = 0x0018, SHOWWINDOW = 0x0018,
SETTINGCHANGE = 0x001A,
ACTIVATEAPP = 0x001C, ACTIVATEAPP = 0x001C,
SETCURSOR = 0x0020, SETCURSOR = 0x0020,
MOUSEACTIVATE = 0x0021, MOUSEACTIVATE = 0x0021,

View File

@ -16,6 +16,7 @@
ShowInTaskbar="False" ShowInTaskbar="False"
Icon="Images/app.dark.png" Icon="Images/app.dark.png"
AllowsTransparency="True" AllowsTransparency="True"
SourceInitialized="OnSourceInitialized"
Loaded="OnLoaded" Loaded="OnLoaded"
Closing="OnClosing" Closing="OnClosing"
Background="Transparent" Background="Transparent"

View File

@ -9,6 +9,7 @@ using System.Timers;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Interop;
using interop; using interop;
using Microsoft.PowerLauncher.Telemetry; using Microsoft.PowerLauncher.Telemetry;
using Microsoft.PowerToys.Telemetry; using Microsoft.PowerToys.Telemetry;
@ -29,8 +30,10 @@ namespace PowerLauncher
private readonly MainViewModel _viewModel; private readonly MainViewModel _viewModel;
private bool _isTextSetProgrammatically; private bool _isTextSetProgrammatically;
private bool _deletePressed; private bool _deletePressed;
private HwndSource _hwndSource;
private Timer _firstDeleteTimer = new Timer(); private Timer _firstDeleteTimer = new Timer();
private bool _coldStateHotkeyPressed; private bool _coldStateHotkeyPressed;
private bool _disposedValue;
public MainWindow(PowerToysRunSettings settings, MainViewModel mainVM) public MainWindow(PowerToysRunSettings settings, MainViewModel mainVM)
: this() : this()
@ -93,6 +96,12 @@ namespace PowerLauncher
Activate(); Activate();
} }
private void OnSourceInitialized(object sender, EventArgs e)
{
_hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
_hwndSource.AddHook(EnvironmentHelper.ProcessWindowMessages);
}
private void OnLoaded(object sender, RoutedEventArgs e) private void OnLoaded(object sender, RoutedEventArgs e)
{ {
WindowsInteropHelper.DisableControlBox(this); WindowsInteropHelper.DisableControlBox(this);
@ -359,8 +368,6 @@ namespace PowerLauncher
} }
} }
private bool disposedValue;
private void QueryTextBox_TextChanged(object sender, TextChangedEventArgs e) private void QueryTextBox_TextChanged(object sender, TextChangedEventArgs e)
{ {
var textBox = (TextBox)sender; var textBox = (TextBox)sender;
@ -451,7 +458,7 @@ namespace PowerLauncher
protected virtual void Dispose(bool disposing) protected virtual void Dispose(bool disposing)
{ {
if (!disposedValue) if (!_disposedValue)
{ {
if (disposing) if (disposing)
{ {
@ -459,12 +466,14 @@ namespace PowerLauncher
{ {
_firstDeleteTimer.Dispose(); _firstDeleteTimer.Dispose();
} }
_hwndSource?.Dispose();
} }
// TODO: free unmanaged resources (unmanaged objects) and override finalizer // TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null // TODO: set large fields to null
_firstDeleteTimer = null; _firstDeleteTimer = null;
disposedValue = true; _disposedValue = true;
} }
} }