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

View file

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

View file

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