Update environment variables changed (#12689)
This commit is contained in:
parent
31a5d49246
commit
e87e06bae6
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
ShowInTaskbar="False"
|
||||
Icon="Images/app.dark.png"
|
||||
AllowsTransparency="True"
|
||||
SourceInitialized="OnSourceInitialized"
|
||||
Loaded="OnLoaded"
|
||||
Closing="OnClosing"
|
||||
Background="Transparent"
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue