mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 03:07:56 +01:00
More things implemented
This commit is contained in:
@@ -11,8 +11,56 @@ namespace RunnerV2.Helpers
|
||||
{
|
||||
internal static partial class ElevationHelper
|
||||
{
|
||||
internal static RestartScheduledMode RestartScheduled { get; set; } = RestartScheduledMode.None;
|
||||
|
||||
internal enum RestartScheduledMode
|
||||
{
|
||||
None,
|
||||
RestartElevated,
|
||||
RestartElevatedWithOpenSettings,
|
||||
RestartNonElevated,
|
||||
}
|
||||
|
||||
private static bool? _cachedValue;
|
||||
|
||||
internal static void RestartIfScheudled()
|
||||
{
|
||||
switch (RestartScheduled)
|
||||
{
|
||||
case RestartScheduledMode.None:
|
||||
return;
|
||||
case RestartScheduledMode.RestartElevated:
|
||||
RestartAsAdministrator("--restartedElevated");
|
||||
break;
|
||||
case RestartScheduledMode.RestartElevatedWithOpenSettings:
|
||||
RestartAsAdministrator("--restartedElevated --open-settings");
|
||||
break;
|
||||
case RestartScheduledMode.RestartNonElevated:
|
||||
// Todo: restart unelevated
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RestartAsAdministrator(string arguments)
|
||||
{
|
||||
ProcessStartInfo processStartInfo = new()
|
||||
{
|
||||
Arguments = arguments,
|
||||
Verb = "runas",
|
||||
UseShellExecute = true,
|
||||
FileName = Environment.ProcessPath,
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
Process.Start(processStartInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Failed to restart as administrator: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsProcessElevated(bool useCachedValue = true)
|
||||
{
|
||||
if (_cachedValue is not null && useCachedValue)
|
||||
|
||||
@@ -112,9 +112,32 @@ namespace RunnerV2.Helpers
|
||||
{
|
||||
switch (property.Name)
|
||||
{
|
||||
case "action":
|
||||
_settingsUtils.SaveSettings(property.Value.GetProperty("general").ToString(), string.Empty);
|
||||
switch (property.Value.GetProperty("general").GetProperty("action_name").GetString())
|
||||
{
|
||||
case "restart_elevation":
|
||||
ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevatedWithOpenSettings;
|
||||
Runner.Close();
|
||||
break;
|
||||
case "request_update_state_date":
|
||||
// Todo:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case "get_all_hotkey_conflicts":
|
||||
// Todo: Handle hotkey conflict
|
||||
break;
|
||||
case "bugreport":
|
||||
TrayIconManager.ProcessTrayMenuCommand((nuint)TrayIconManager.TrayButton.ReportBug);
|
||||
break;
|
||||
case "bug_report_status":
|
||||
_ipc?.Send($@"{{""bug_report_running:"" {(TrayIconManager.IsBugReportToolRunning ? "true" : "false")}");
|
||||
break;
|
||||
case "killrunner":
|
||||
Runner.Close();
|
||||
break;
|
||||
case "general":
|
||||
_settingsUtils.SaveSettings(property.Value.ToString(), string.Empty);
|
||||
foreach (IPowerToysModule module in Runner.LoadedModules)
|
||||
@@ -124,25 +147,38 @@ namespace RunnerV2.Helpers
|
||||
}
|
||||
|
||||
break;
|
||||
case string s:
|
||||
_settingsUtils.SaveSettings(property.Value.ToString(), s);
|
||||
case "powertoys":
|
||||
foreach (var powertoysSettingsPart in property.Value.EnumerateObject())
|
||||
{
|
||||
_settingsUtils.SaveSettings(property.Value.ToString(), powertoysSettingsPart.Name);
|
||||
|
||||
if (Runner.LoadedModules.Find(m => m.Name == s) is IPowerToysModule moduleFound)
|
||||
{
|
||||
moduleFound.OnSettingsChanged(s, property.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no specific module was found, notify all enabled modules
|
||||
foreach (IPowerToysModule module in Runner.LoadedModules.Where(m => m.Enabled))
|
||||
if (Runner.LoadedModules.Find(m => m.Name == powertoysSettingsPart.Name) is IPowerToysModule module)
|
||||
{
|
||||
module.OnSettingsChanged(s, property.Value);
|
||||
module.OnSettingsChanged(powertoysSettingsPart.Name, powertoysSettingsPart.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no specific module was found, notify all enabled modules
|
||||
foreach (IPowerToysModule module2 in Runner.LoadedModules.Where(m => m.Enabled))
|
||||
{
|
||||
module2.OnSettingsChanged(powertoysSettingsPart.Name, powertoysSettingsPart.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Console.WriteLine($"Unknown message received from Settings: {property.Name}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CloseSettingsWindow()
|
||||
{
|
||||
InteropEvent closeEventWrapper = new(InteropEvent.SettingsTerminate);
|
||||
closeEventWrapper.Fire();
|
||||
closeEventWrapper.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace RunnerV2.Helpers
|
||||
Shell_NotifyIcon(NIMDELETE, ref notifyicondata);
|
||||
}
|
||||
|
||||
private enum TrayButton : uint
|
||||
internal enum TrayButton : uint
|
||||
{
|
||||
Settings = 1,
|
||||
Documentation,
|
||||
@@ -102,6 +102,8 @@ namespace RunnerV2.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsBugReportToolRunning { get; set; }
|
||||
|
||||
internal static void ProcessTrayMenuCommand(nuint commandId)
|
||||
{
|
||||
switch ((TrayButton)commandId)
|
||||
@@ -132,9 +134,11 @@ namespace RunnerV2.Helpers
|
||||
{
|
||||
bugReportProcess.Dispose();
|
||||
EnableMenuItem(_trayIconMenu, (uint)TrayButton.ReportBug, 0x00000000);
|
||||
IsBugReportToolRunning = false;
|
||||
};
|
||||
|
||||
bugReportProcess.Start();
|
||||
IsBugReportToolRunning = true;
|
||||
|
||||
break;
|
||||
case TrayButton.Close:
|
||||
|
||||
@@ -17,9 +17,8 @@ using Settings.UI.Library;
|
||||
internal sealed class Program
|
||||
{
|
||||
private static readonly SettingsUtils _settingsUtils = new();
|
||||
private static GeneralSettings _generalSettings = _settingsUtils.GetSettings<GeneralSettings>();
|
||||
|
||||
public static GeneralSettings GeneralSettings => _generalSettings;
|
||||
internal static GeneralSettings GeneralSettings => _settingsUtils.GetSettings<GeneralSettings>();
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
@@ -46,13 +45,13 @@ internal sealed class Program
|
||||
|
||||
bool isElevated = ElevationHelper.IsProcessElevated();
|
||||
bool hasDontElevateArgument = args.Contains("--dont-elevate");
|
||||
bool runElevatedSetting = _generalSettings.RunElevated;
|
||||
bool runElevatedSetting = GeneralSettings.RunElevated;
|
||||
bool hasRestartedElevatedArgment = args.Contains("--restartedElevated");
|
||||
|
||||
Action afterInitializationAction = () => { };
|
||||
Version version = Assembly.GetExecutingAssembly().GetName().Version!;
|
||||
|
||||
if ($"v{version.Major}.{version.Minor}.{version.Build}" != _settingsUtils.GetSettings<LastVersionRunSettings>(fileName: "last_version_run.json").LastVersion && (!_generalSettings.ShowWhatsNewAfterUpdates || GPOWrapper.GetDisableShowWhatsNewAfterUpdatesValue() != GpoRuleConfigured.Disabled))
|
||||
if ($"v{version.Major}.{version.Minor}.{version.Build}" != _settingsUtils.GetSettings<LastVersionRunSettings>(fileName: "last_version_run.json").LastVersion && (!GeneralSettings.ShowWhatsNewAfterUpdates || GPOWrapper.GetDisableShowWhatsNewAfterUpdatesValue() != GpoRuleConfigured.Disabled))
|
||||
{
|
||||
afterInitializationAction += () =>
|
||||
{
|
||||
@@ -68,6 +67,14 @@ internal sealed class Program
|
||||
};
|
||||
}
|
||||
|
||||
if (shouldOpenSettings)
|
||||
{
|
||||
afterInitializationAction += () =>
|
||||
{
|
||||
SettingsHelper.OpenSettingsWindow(additionalArguments: shouldOpenSettingsToSpecificPage ? args.First(s => s.StartsWith("--open-settings=", StringComparison.InvariantCulture)).Replace("--open-settings=", string.Empty, StringComparison.InvariantCulture) : null);
|
||||
};
|
||||
}
|
||||
|
||||
// Set last version run
|
||||
_settingsUtils.SaveSettings(new LastVersionRunSettings() { LastVersion = $"v{version.Major}.{version.Minor}.{version.Build}" }.ToJsonString(), fileName: "last_version_run.json");
|
||||
|
||||
@@ -80,14 +87,18 @@ internal sealed class Program
|
||||
case (_, _, false, _):
|
||||
case (_, true, _, _):
|
||||
case (false, _, _, true):
|
||||
_ = Runner.Run(afterInitializationAction);
|
||||
GeneralSettings tempGeneralSettings = GeneralSettings;
|
||||
tempGeneralSettings.IsElevated = isElevated;
|
||||
_settingsUtils.SaveSettings(tempGeneralSettings.ToJsonString());
|
||||
|
||||
// Todo: Save settings
|
||||
_ = Runner.Run(afterInitializationAction);
|
||||
break;
|
||||
default:
|
||||
// Todo: scheudle restart as elevated
|
||||
throw new NotImplementedException();
|
||||
ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevated;
|
||||
break;
|
||||
}
|
||||
|
||||
ElevationHelper.RestartIfScheudled();
|
||||
}
|
||||
|
||||
private static SpecialMode ShouldRunInSpecialMode(string[] args)
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace RunnerV2
|
||||
|
||||
internal static bool Run(Action afterInitializationAction)
|
||||
{
|
||||
// Todo: Start tray icon
|
||||
TrayIconManager.StartTrayIcon();
|
||||
FrozenSet<string> modulesToLoad = ["PowerToys.AlwaysOnTopModuleInterface.dll", "WinUI3Apps\\PowerToys.Hosts.dll"];
|
||||
|
||||
@@ -78,21 +77,24 @@ namespace RunnerV2
|
||||
|
||||
private static void MessageLoop()
|
||||
{
|
||||
while (true)
|
||||
while (GetMessageW(out MSG msg, IntPtr.Zero, 0, 0) != 0)
|
||||
{
|
||||
if (GetMessageW(out MSG msg, IntPtr.Zero, 0, 0) != 0)
|
||||
{
|
||||
TranslateMessage(ref msg);
|
||||
DispatchMessageW(ref msg);
|
||||
TranslateMessage(ref msg);
|
||||
DispatchMessageW(ref msg);
|
||||
|
||||
HandleMessage(msg.HWnd, msg.Message, (nint)msg.WParam, (nint)msg.LParam);
|
||||
}
|
||||
HandleMessage(msg.HWnd, msg.Message, (nint)msg.WParam, (nint)msg.LParam);
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
internal static void Close()
|
||||
{
|
||||
TrayIconManager.StopTrayIcon();
|
||||
SettingsHelper.CloseSettingsWindow();
|
||||
ElevationHelper.RestartIfScheudled();
|
||||
|
||||
foreach (IPowerToysModule module in _successfullyAddedModules)
|
||||
{
|
||||
try
|
||||
@@ -193,12 +195,21 @@ namespace RunnerV2
|
||||
}
|
||||
}
|
||||
|
||||
private static bool _handledShortcut;
|
||||
|
||||
private static IntPtr HandleMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case (uint)WindowMessages.HOTKEY:
|
||||
if (_handledShortcut)
|
||||
{
|
||||
_handledShortcut = false;
|
||||
break;
|
||||
}
|
||||
|
||||
HotkeyManager.ProcessHotkey((nuint)wParam);
|
||||
_handledShortcut = true;
|
||||
break;
|
||||
case (uint)WindowMessages.ICON_NOTIFY:
|
||||
TrayIconManager.ProcessTrayIconMessage(lParam);
|
||||
@@ -210,7 +221,7 @@ namespace RunnerV2
|
||||
TrayIconManager.StartTrayIcon();
|
||||
break;
|
||||
case (uint)WindowMessages.DESTROY:
|
||||
TrayIconManager.StopTrayIcon();
|
||||
Close();
|
||||
break;
|
||||
default:
|
||||
if (msg == _taskbarCreatedMessage)
|
||||
|
||||
47
src/common/ManagedCommon/InteropEvent.cs
Normal file
47
src/common/ManagedCommon/InteropEvent.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
// 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 static ManagedCommon.NativeMethods;
|
||||
|
||||
namespace ManagedCommon
|
||||
{
|
||||
public partial class InteropEvent : IDisposable
|
||||
{
|
||||
public const string AlwaysOnTopPin = "Local\\AlwaysOnTopPinEvent-892e0aa2-cfa8-4cc4-b196-ddeb32314ce8";
|
||||
public const string AlwaysOnTopTerminate = "Local\\AlwaysOnTopTerminateEvent-cfdf1eae-791f-4953-8021-2f18f3837eae";
|
||||
public const string SettingsTerminate = "Local\\PowerToysRunnerTerminateSettingsEvent-c34cb661-2e69-4613-a1f8-4e39c25d7ef6";
|
||||
|
||||
private IntPtr _eventHandle;
|
||||
|
||||
public InteropEvent(string eventName)
|
||||
{
|
||||
_eventHandle = CreateEventW(IntPtr.Zero, false, false, eventName);
|
||||
}
|
||||
|
||||
public void Fire()
|
||||
{
|
||||
if (_eventHandle != IntPtr.Zero)
|
||||
{
|
||||
SetEvent(_eventHandle);
|
||||
}
|
||||
}
|
||||
|
||||
~InteropEvent()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_eventHandle != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(_eventHandle);
|
||||
_eventHandle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace ManagedCommon
|
||||
{
|
||||
internal static class NativeMethods
|
||||
internal static partial class NativeMethods
|
||||
{
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
|
||||
@@ -21,6 +21,13 @@ namespace ManagedCommon
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, System.Text.StringBuilder lpExeName, ref uint lpdwSize);
|
||||
|
||||
[LibraryImport("kernel32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial IntPtr CreateEventW(IntPtr lpEventAttributes, [MarshalAs(UnmanagedType.Bool)] bool bManualReset, [MarshalAs(UnmanagedType.Bool)] bool bInitialState, string lpName);
|
||||
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool SetEvent(IntPtr hEvent);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ using PowerToys.GPOWrapper;
|
||||
|
||||
namespace AlwaysOnTopModuleInterface
|
||||
{
|
||||
public class ModuleInterface : IPowerToysModule
|
||||
public partial class ModuleInterface : IPowerToysModule, IDisposable
|
||||
{
|
||||
public bool Enabled => true;
|
||||
public bool Enabled => new SettingsUtils().GetSettings<GeneralSettings>().Enabled.AlwaysOnTop;
|
||||
|
||||
public string Name => "AlwaysOnTop";
|
||||
|
||||
@@ -22,24 +22,22 @@ namespace AlwaysOnTopModuleInterface
|
||||
|
||||
private Process? _process;
|
||||
|
||||
private IntPtr pinEvent = CreateEventW(IntPtr.Zero, false, false, "Local\\AlwaysOnTopPinEvent-892e0aa2-cfa8-4cc4-b196-ddeb32314ce8");
|
||||
private InteropEvent? _pinEventWrapper;
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
if (_process is not null && !_process.HasExited)
|
||||
{
|
||||
_process.Kill();
|
||||
}
|
||||
|
||||
if (pinEvent != IntPtr.Zero)
|
||||
{
|
||||
CloseHandle(pinEvent);
|
||||
pinEvent = IntPtr.Zero;
|
||||
}
|
||||
InteropEvent terminateEventWrapper = new(InteropEvent.AlwaysOnTopTerminate);
|
||||
terminateEventWrapper.Fire();
|
||||
terminateEventWrapper.Dispose();
|
||||
_process?.Dispose();
|
||||
_pinEventWrapper?.Dispose();
|
||||
_pinEventWrapper = null;
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
_pinEventWrapper = new InteropEvent(InteropEvent.AlwaysOnTopPin);
|
||||
|
||||
var psi = new ProcessStartInfo
|
||||
{
|
||||
FileName = "PowerToys.AlwaysOnTop.exe",
|
||||
@@ -54,19 +52,17 @@ namespace AlwaysOnTopModuleInterface
|
||||
|
||||
public Action OnHotkey => () =>
|
||||
{
|
||||
if (_process is not null && !_process.HasExited && pinEvent != IntPtr.Zero)
|
||||
if (!_process?.HasExited ?? false)
|
||||
{
|
||||
_ = SetEvent(pinEvent);
|
||||
_pinEventWrapper?.Fire();
|
||||
}
|
||||
};
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
internal static extern IntPtr CreateEventW(IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern bool SetEvent(IntPtr hEvent);
|
||||
public void Dispose()
|
||||
{
|
||||
_process?.Dispose();
|
||||
_pinEventWrapper?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user