From 77a8555fd43f4539eee0d5db1d58e9a8fe1b12c1 Mon Sep 17 00:00:00 2001 From: Noraa Junker Date: Sun, 16 Nov 2025 22:50:40 +0100 Subject: [PATCH] push --- PowerToys.sln | 47 ++- .../RunnerV2/Helpers/ElevationHelper.cs | 42 +++ .../RunnerV2/Helpers/HotkeyManager.cs | 55 ++++ .../RunnerV2/Helpers/SettingsHelper.cs | 148 +++++++++ .../RunnerV2/Helpers/TrayIconManager.cs | 134 ++++++++ src/RunnerV2/RunnerV2/Models/SpecialMode.cs | 14 + src/RunnerV2/RunnerV2/NativeMethods.cs | 176 ++++++++++ src/RunnerV2/RunnerV2/Program.cs | 98 ++++++ src/RunnerV2/RunnerV2/Runner.cs | 212 +++++++++++++ src/RunnerV2/RunnerV2/RunnerV2.csproj | 20 ++ src/RunnerV2/RunnerV2/app.manifest | 18 ++ src/RunnerV2/RunnerV2/icon.ico | Bin 0 -> 53114 bytes src/common/GPOWrapperProjection/GPOWrapper.cs | 5 + src/common/ManagedCommon/HotkeyEx.cs | 8 + src/common/ManagedCommon/IPowerToysModule.cs | 29 ++ src/common/ManagedCommon/LanguageHelper.cs | 4 +- src/common/ManagedCommon/Logger.cs | 6 +- src/common/ManagedCommon/ManagedCommon.csproj | 2 + src/common/ManagedCommon/ThemeHelpers.cs | 2 +- src/common/ManagedCommon/ThemeListener.cs | 4 +- src/modules/Hosts/Hosts/Hosts.csproj | 9 +- src/modules/Hosts/Hosts/ModuleInterface.cs | 34 ++ .../HostsModuleInterface.base.rc | 40 --- .../HostsModuleInterface.vcxproj | 93 ------ .../HostsModuleInterface.vcxproj.filters | 59 ---- .../Hosts/HostsModuleInterface/Resource.resx | 124 -------- .../Hosts/HostsModuleInterface/dllmain.cpp | 300 ------------------ .../HostsModuleInterface/packages.config | 4 - .../Hosts/HostsModuleInterface/pch.cpp | 1 - src/modules/Hosts/HostsModuleInterface/pch.h | 4 - .../HostsModuleInterface/resource.base.h | 13 - .../Hosts/HostsModuleInterface/trace.cpp | 32 -- .../Hosts/HostsModuleInterface/trace.h | 13 - .../AlwaysOnTopModuleInterface.csproj | 18 ++ .../AlwaysOnTopModuleInterface.rc | 40 --- .../AlwaysOnTopModuleInterface.vcxproj | 82 ----- ...AlwaysOnTopModuleInterface.vcxproj.filters | 53 ---- .../ModuleInterface.cs | 72 +++++ .../AlwaysOnTopModuleInterface/dllmain.cpp | 300 ------------------ .../packages.config | 5 - .../AlwaysOnTopModuleInterface/pch.cpp | 1 - .../AlwaysOnTopModuleInterface/pch.h | 9 - .../AlwaysOnTopModuleInterface/resource.h | 13 - .../AlwaysOnTopModuleInterface/targetver.h | Bin 630 -> 0 bytes .../LastVersionRunSettings.cs | 32 ++ .../Settings.UI.Library/OOBESettings.cs | 32 ++ .../Settings.UI/PowerToys.Settings.csproj | 4 +- 47 files changed, 1183 insertions(+), 1228 deletions(-) create mode 100644 src/RunnerV2/RunnerV2/Helpers/ElevationHelper.cs create mode 100644 src/RunnerV2/RunnerV2/Helpers/HotkeyManager.cs create mode 100644 src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs create mode 100644 src/RunnerV2/RunnerV2/Helpers/TrayIconManager.cs create mode 100644 src/RunnerV2/RunnerV2/Models/SpecialMode.cs create mode 100644 src/RunnerV2/RunnerV2/NativeMethods.cs create mode 100644 src/RunnerV2/RunnerV2/Program.cs create mode 100644 src/RunnerV2/RunnerV2/Runner.cs create mode 100644 src/RunnerV2/RunnerV2/RunnerV2.csproj create mode 100644 src/RunnerV2/RunnerV2/app.manifest create mode 100644 src/RunnerV2/RunnerV2/icon.ico create mode 100644 src/common/ManagedCommon/HotkeyEx.cs create mode 100644 src/common/ManagedCommon/IPowerToysModule.cs create mode 100644 src/modules/Hosts/Hosts/ModuleInterface.cs delete mode 100644 src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.base.rc delete mode 100644 src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj delete mode 100644 src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj.filters delete mode 100644 src/modules/Hosts/HostsModuleInterface/Resource.resx delete mode 100644 src/modules/Hosts/HostsModuleInterface/dllmain.cpp delete mode 100644 src/modules/Hosts/HostsModuleInterface/packages.config delete mode 100644 src/modules/Hosts/HostsModuleInterface/pch.cpp delete mode 100644 src/modules/Hosts/HostsModuleInterface/pch.h delete mode 100644 src/modules/Hosts/HostsModuleInterface/resource.base.h delete mode 100644 src/modules/Hosts/HostsModuleInterface/trace.cpp delete mode 100644 src/modules/Hosts/HostsModuleInterface/trace.h create mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.csproj delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.rc delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj.filters create mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/ModuleInterface.cs delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/dllmain.cpp delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/packages.config delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.cpp delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.h delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/resource.h delete mode 100644 src/modules/alwaysontop/AlwaysOnTopModuleInterface/targetver.h create mode 100644 src/settings-ui/Settings.UI.Library/LastVersionRunSettings.cs create mode 100644 src/settings-ui/Settings.UI.Library/OOBESettings.cs diff --git a/PowerToys.sln b/PowerToys.sln index e34779c5bb..ac70abbfe9 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32014.148 +# Visual Studio Version 18 +VisualStudioVersion = 18.3.11206.111 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner.vcxproj", "{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}" ProjectSection(ProjectDependencies) = postProject @@ -374,8 +374,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AlwaysOnTop", "AlwaysOnTop" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AlwaysOnTop", "src\modules\alwaysontop\AlwaysOnTop\AlwaysOnTop.vcxproj", "{1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AlwaysOnTopModuleInterface", "src\modules\alwaysontop\AlwaysOnTopModuleInterface\AlwaysOnTopModuleInterface.vcxproj", "{48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.WebSearch", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.WebSearch\Community.PowerToys.Run.Plugin.WebSearch.csproj", "{9F94B303-5E21-4364-9362-64426F8DB932}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MousePointerCrosshairs", "src\modules\MouseUtils\MousePointerCrosshairs\MousePointerCrosshairs.vcxproj", "{EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E}" @@ -443,8 +441,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hosts", "Hosts", "{F05E590D EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostsEditor.UnitTests", "src\modules\Hosts\Hosts.Tests\HostsEditor.UnitTests.csproj", "{E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HostsModuleInterface", "src\modules\Hosts\HostsModuleInterface\HostsModuleInterface.vcxproj", "{B41B888C-7DB8-4747-B262-4062E05A230D}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FileLocksmith", "FileLocksmith", "{AB82E5DD-C32D-4F28-9746-2C780846188E}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithExt", "src\modules\FileLocksmith\FileLocksmithExt\FileLocksmithExt.vcxproj", "{57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}" @@ -834,6 +830,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LanguageModelProvider", "sr EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.UI.ViewModels.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.UI.ViewModels.UnitTests\Microsoft.CmdPal.UI.ViewModels.UnitTests.csproj", "{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RunnerV2", "src\RunnerV2\RunnerV2\RunnerV2.csproj", "{20C43796-E14D-47B2-843A-843CAC9C0D28}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AlwaysOnTopModuleInterface", "src\modules\alwaysontop\AlwaysOnTopModuleInterface\AlwaysOnTopModuleInterface.csproj", "{2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -1610,14 +1610,6 @@ Global {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Release|ARM64.Build.0 = Release|ARM64 {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Release|x64.ActiveCfg = Release|x64 {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2}.Release|x64.Build.0 = Release|x64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Debug|ARM64.Build.0 = Debug|ARM64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Debug|x64.ActiveCfg = Debug|x64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Debug|x64.Build.0 = Debug|x64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Release|ARM64.ActiveCfg = Release|ARM64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Release|ARM64.Build.0 = Release|ARM64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Release|x64.ActiveCfg = Release|x64 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9}.Release|x64.Build.0 = Release|x64 {9F94B303-5E21-4364-9362-64426F8DB932}.Debug|ARM64.ActiveCfg = Debug|ARM64 {9F94B303-5E21-4364-9362-64426F8DB932}.Debug|ARM64.Build.0 = Debug|ARM64 {9F94B303-5E21-4364-9362-64426F8DB932}.Debug|x64.ActiveCfg = Debug|x64 @@ -1826,14 +1818,6 @@ Global {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Release|ARM64.Build.0 = Release|ARM64 {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Release|x64.ActiveCfg = Release|x64 {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A}.Release|x64.Build.0 = Release|x64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Debug|ARM64.ActiveCfg = Debug|ARM64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Debug|ARM64.Build.0 = Debug|ARM64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Debug|x64.ActiveCfg = Debug|x64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Debug|x64.Build.0 = Debug|x64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Release|ARM64.ActiveCfg = Release|ARM64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Release|ARM64.Build.0 = Release|ARM64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Release|x64.ActiveCfg = Release|x64 - {B41B888C-7DB8-4747-B262-4062E05A230D}.Release|x64.Build.0 = Release|x64 {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|ARM64.ActiveCfg = Debug|ARM64 {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|ARM64.Build.0 = Debug|ARM64 {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE}.Debug|x64.ActiveCfg = Debug|x64 @@ -3036,6 +3020,22 @@ Global {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|ARM64.Build.0 = Release|ARM64 {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|x64.ActiveCfg = Release|x64 {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|x64.Build.0 = Release|x64 + {20C43796-E14D-47B2-843A-843CAC9C0D28}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {20C43796-E14D-47B2-843A-843CAC9C0D28}.Debug|ARM64.Build.0 = Debug|ARM64 + {20C43796-E14D-47B2-843A-843CAC9C0D28}.Debug|x64.ActiveCfg = Debug|x64 + {20C43796-E14D-47B2-843A-843CAC9C0D28}.Debug|x64.Build.0 = Debug|x64 + {20C43796-E14D-47B2-843A-843CAC9C0D28}.Release|ARM64.ActiveCfg = Release|ARM64 + {20C43796-E14D-47B2-843A-843CAC9C0D28}.Release|ARM64.Build.0 = Release|ARM64 + {20C43796-E14D-47B2-843A-843CAC9C0D28}.Release|x64.ActiveCfg = Release|x64 + {20C43796-E14D-47B2-843A-843CAC9C0D28}.Release|x64.Build.0 = Release|x64 + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}.Debug|ARM64.Build.0 = Debug|ARM64 + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}.Debug|x64.ActiveCfg = Debug|x64 + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}.Debug|x64.Build.0 = Debug|x64 + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}.Release|ARM64.ActiveCfg = Release|ARM64 + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}.Release|ARM64.Build.0 = Release|ARM64 + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}.Release|x64.ActiveCfg = Release|x64 + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -3150,7 +3150,6 @@ Global {FCF3E52D-B80A-4FC3-98FD-6391354F0EE3} = {6B01F1CF-F4DB-48B5-BFE7-0BF576C1D704} {60CD2D4F-C3B9-4897-9821-FCA5098B41CE} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} {1DC3BE92-CE89-43FB-8110-9C043A2FE7A2} = {60CD2D4F-C3B9-4897-9821-FCA5098B41CE} - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9} = {60CD2D4F-C3B9-4897-9821-FCA5098B41CE} {9F94B303-5E21-4364-9362-64426F8DB932} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {EAE14C0E-7A6B-45DA-9080-A7D8C077BA6E} = {322566EF-20DC-43A6-B9F8-616AF942579A} {F7C8C0F1-5431-4347-89D0-8E5354F93CF2} = {2F305555-C296-497E-AC20-5FA1B237996A} @@ -3182,7 +3181,6 @@ Global {31D1C81D-765F-4446-AA62-E743F6325049} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} {E2D03E0F-7A75-4813-9F4B-D8763D43FD3A} = {1C48CD47-D610-463A-A53C-AF82DD6C47E7} - {B41B888C-7DB8-4747-B262-4062E05A230D} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} {AB82E5DD-C32D-4F28-9746-2C780846188E} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} {57175EC7-92A5-4C1E-8244-E3FBCA2A81DE} = {AB82E5DD-C32D-4F28-9746-2C780846188E} {E69B044A-2F8A-45AA-AD0B-256C59421807} = {AB82E5DD-C32D-4F28-9746-2C780846188E} @@ -3367,6 +3365,7 @@ Global {4E0FCF69-B06B-D272-76BF-ED3A559B4EDA} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} {45354F4F-1414-45CE-B600-51CD1209FD19} = {1AFB6476-670D-4E80-A464-657E01DFF482} {A66E9270-5D93-EC9C-F06E-CE7295BB9A6C} = {8EF25507-2575-4ADE-BF7E-D23376903AB8} + {2CF11A08-1A1F-4F75-BC41-F982FCF26D2F} = {60CD2D4F-C3B9-4897-9821-FCA5098B41CE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0} diff --git a/src/RunnerV2/RunnerV2/Helpers/ElevationHelper.cs b/src/RunnerV2/RunnerV2/Helpers/ElevationHelper.cs new file mode 100644 index 0000000000..80dc82631e --- /dev/null +++ b/src/RunnerV2/RunnerV2/Helpers/ElevationHelper.cs @@ -0,0 +1,42 @@ +// 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.Diagnostics; +using System.Runtime.InteropServices; +using static RunnerV2.NativeMethods; + +namespace RunnerV2.Helpers +{ + internal static partial class ElevationHelper + { + private static bool? _cachedValue; + + internal static bool IsProcessElevated(bool useCachedValue = true) + { + if (_cachedValue is not null && useCachedValue) + { + return _cachedValue.Value; + } + + bool elevated = false; + if (OpenProcessToken(Process.GetCurrentProcess().Handle, TOKENQUERY, out nint token)) + { + TokenElevation elevation = default; + if (GetTokenInformation(token, TOKEN_INFORMATION_CLASS.TOKEN_ELEVATION, ref elevation, (uint)Marshal.SizeOf(elevation), out uint _)) + { + elevated = elevation.TokenIsElevated != 0; + } + + if (token != IntPtr.Zero) + { + CloseHandle(token); + } + } + + _cachedValue = elevated; + return elevated; + } + } +} diff --git a/src/RunnerV2/RunnerV2/Helpers/HotkeyManager.cs b/src/RunnerV2/RunnerV2/Helpers/HotkeyManager.cs new file mode 100644 index 0000000000..88901182de --- /dev/null +++ b/src/RunnerV2/RunnerV2/Helpers/HotkeyManager.cs @@ -0,0 +1,55 @@ +// 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.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using ManagedCommon; +using static RunnerV2.NativeMethods; + +namespace RunnerV2.Helpers +{ + internal static partial class HotkeyManager + { + private static readonly Dictionary _hotkeyActions = []; + + public static void EnableHotkey(HotkeyEx hotkey, Action onHotkey) + { + if (_hotkeyActions.ContainsKey(hotkey)) + { + return; + } + + _hotkeyActions[hotkey] = onHotkey; + + if (!RegisterHotKey(Runner.RunnerHwnd, hotkey.GetHashCode(), hotkey.ModifiersMask, hotkey.VkCode)) + { + Console.WriteLine("Failed to register hotkey: " + hotkey); + var lastError = Marshal.GetLastWin32Error(); + Console.WriteLine("LastError: " + lastError); + } + } + + public static void DisableHotkey(HotkeyEx hotkey) + { + if (!_hotkeyActions.ContainsKey(hotkey)) + { + return; + } + + _hotkeyActions.Remove(hotkey); + UnregisterHotKey(IntPtr.Zero, hotkey.GetHashCode()); + } + + public static void ProcessHotkey(nuint hotkeyId) + { + ulong hashId = hotkeyId.ToUInt64(); + if (_hotkeyActions.Any(h => h.Key.GetHashCode() == (int)hashId)) + { + _hotkeyActions.First(h => h.Key.GetHashCode() == (int)hashId).Value(); + } + } + } +} diff --git a/src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs b/src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs new file mode 100644 index 0000000000..51e57e45b0 --- /dev/null +++ b/src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs @@ -0,0 +1,148 @@ +// 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.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.IO; +using System.IO.Pipelines; +using System.Linq; +using System.Text.Json; +using ManagedCommon; +using Microsoft.PowerToys.Settings.UI.Library; +using PowerToys.Interop; + +namespace RunnerV2.Helpers +{ + internal static class SettingsHelper + { + private static Process? _process; + private static TwoWayPipeMessageIPCManaged? _ipc; + private static SettingsUtils _settingsUtils = new(); + + public static void OpenSettingsWindow(bool showOobeWindow = false, bool showScoobeWindow = false, bool showFlyout = false, Point? flyoutPosition = null, string? additionalArguments = null) + { + if (_process is not null && _ipc is not null && !_process.HasExited) + { + if (showFlyout) + { + _ipc.Send(@"{""ShowYourself"": ""flyout""}"); + } + else + { + _ipc.Send($@"{{""ShowYourself"": ""{additionalArguments ?? "Dashboard"}""}}"); + } + + return; + } + + _ipc?.End(); + _ipc = null; + + // Arg 1: Executable path + string executablePath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) ?? throw new InvalidOperationException("No executable path found"), "WinUI3Apps", "PowerToys.Settings.exe"); + + // Arg 2,3: Pipe names + Pipe settingsPipe = new(); + Pipe powertoysPipe = new(); + + string powerToysPipeName = @"\\.\pipe\powertoys_runner_" + Guid.NewGuid(); + string settingsPipeName = @"\\.\pipe\powertoys_settings_" + Guid.NewGuid(); + + // Arg 4: Process pid + string currentProcessId = Environment.ProcessId.ToString(CultureInfo.InvariantCulture); + + // Arg 5: Settings theme + string theme = Program.GeneralSettings.Theme switch + { + "light" => "light", + "dark" => "dark", + "system" when ThemeHelpers.GetAppTheme() == AppTheme.Light => "light", + "system" when ThemeHelpers.GetAppTheme() == AppTheme.Dark => "dark", + _ => throw new NotImplementedException(), + }; + + // Arg 6: Elevated status + string isElevated = Program.GeneralSettings.IsElevated ? "true" : "false"; + + // Arg 7: Is user an administrator + string isAdmin = Program.GeneralSettings.IsAdmin ? "true" : "false"; + + // Arg 8: Show OOBE window + string showOobeArg = showOobeWindow ? "true" : "false"; + + // Arg 9: Show SCOOBE window + string showScoobeArg = showScoobeWindow ? "true" : "false"; + + // Arg 10: Show flyout + string showFlyoutArg = showFlyout ? "true" : "false"; + + // Arg 11: Are there additional settings window arguments + string areThereadditionalArgs = string.IsNullOrEmpty(additionalArguments) ? "false" : "true"; + + // Arg 12: Are there flyout position arguments + string areThereFlyoutPositionArgs = flyoutPosition.HasValue ? "true" : "false"; + + string executableArgs = $"{powerToysPipeName} {settingsPipeName} {currentProcessId} {theme} {isElevated} {isAdmin} {showOobeArg} {showScoobeArg} {showFlyoutArg} {areThereadditionalArgs} {areThereFlyoutPositionArgs}"; + + if (!string.IsNullOrEmpty(additionalArguments)) + { + executableArgs += $" {additionalArguments}"; + } + + if (flyoutPosition is not null) + { + executableArgs += $" {flyoutPosition.Value.X} {flyoutPosition.Value.Y}"; + } + + _process = Process.Start(executablePath, executableArgs); + + // Initialize listening to pipes + _ipc = new TwoWayPipeMessageIPCManaged(powerToysPipeName, settingsPipeName, OnSettingsMessageReceived); + _ipc.Start(); + } + + private static void OnSettingsMessageReceived(string message) + { + JsonDocument messageDocument = JsonDocument.Parse(message); + + foreach (var property in messageDocument.RootElement.EnumerateObject()) + { + switch (property.Name) + { + case "get_all_hotkey_conflicts": + // Todo: Handle hotkey conflict + break; + case "general": + _settingsUtils.SaveSettings(property.Value.ToString(), string.Empty); + foreach (IPowerToysModule module in Runner.LoadedModules) + { + module.OnSettingsChanged("general", property.Value); + Runner.ToggleModuleStateBasedOnEnabledProperty(module); + } + + break; + case string s: + _settingsUtils.SaveSettings(property.Value.ToString(), s); + + 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)) + { + module.OnSettingsChanged(s, property.Value); + } + } + + break; + } + } + } + } +} diff --git a/src/RunnerV2/RunnerV2/Helpers/TrayIconManager.cs b/src/RunnerV2/RunnerV2/Helpers/TrayIconManager.cs new file mode 100644 index 0000000000..9927453f5a --- /dev/null +++ b/src/RunnerV2/RunnerV2/Helpers/TrayIconManager.cs @@ -0,0 +1,134 @@ +// 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.Diagnostics; +using System.Drawing; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using System.Windows.Forms; +using static RunnerV2.NativeMethods; + +namespace RunnerV2.Helpers +{ + internal static partial class TrayIconManager + { + internal static void StartTrayIcon() + { + NOTIFYICONDATA notifyicondata = new() + { + CbSize = (uint)Marshal.SizeOf(), + HWnd = Runner.RunnerHwnd, + UId = 1, + HIcon = Icon.ExtractAssociatedIcon(Environment.ProcessPath!)!.Handle, + UFlags = 0x0000001 | 0x00000002 | 0x4, + UCallbackMessage = (uint)WindowMessages.ICON_NOTIFY, + SzTip = "PowerToys Runner", + }; + + ChangeWindowMessageFilterEx(Runner.RunnerHwnd, 0x0111, 0x0001, IntPtr.Zero); + + Shell_NotifyIcon(NIMADD, ref notifyicondata); + } + + private enum TrayButton : uint + { + Settings = 1, + Documentation, + ReportBug, + Close, + } + + private static bool _doubleClickTimerRunning; + private static bool _doubleClickDetected; + + private static IntPtr _trayIconMenu; + + static TrayIconManager() + { + _trayIconMenu = CreatePopupMenu(); + AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Settings), "Settings\tDouble-click"); + AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // separator + AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Documentation), "Documentation"); + AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.ReportBug), "Report a Bug"); + AppendMenuW(_trayIconMenu, 0x00000800u, UIntPtr.Zero, string.Empty); // separator + AppendMenuW(_trayIconMenu, 0u, new UIntPtr((uint)TrayButton.Close), "Close"); + } + + internal static void ProcessTrayIconMessage(long lParam) + { + switch (lParam) + { + case 0x0205: // WM_RBUTTONDBLCLK + case 0x007B: // WM_CONTEXTMENU + SetForegroundWindow(Runner.RunnerHwnd); + TrackPopupMenu(_trayIconMenu, 0x0004 | 0x0020, Cursor.Position.X, Cursor.Position.Y, 0, Runner.RunnerHwnd, IntPtr.Zero); + break; + case 0x0202: // WM_LBUTTONUP + if (_doubleClickTimerRunning) + { + break; + } + + _doubleClickTimerRunning = true; + Task.Delay(SystemInformation.DoubleClickTime).ContinueWith(_ => + { + if (!_doubleClickDetected) + { + SettingsHelper.OpenSettingsWindow(showFlyout: true, flyoutPosition: Cursor.Position); + } + + _doubleClickDetected = false; + _doubleClickTimerRunning = false; + }); + break; + case 0x0203: // WM_LBUTTONDBLCLK + _doubleClickDetected = true; + SettingsHelper.OpenSettingsWindow(); + break; + } + } + + internal static void ProcessTrayMenuCommand(nuint commandId) + { + switch ((TrayButton)commandId) + { + case TrayButton.Settings: + SettingsHelper.OpenSettingsWindow(); + break; + case TrayButton.Documentation: + Process.Start(new ProcessStartInfo + { + FileName = "https://aka.ms/PowerToysOverview", + UseShellExecute = true, + }); + break; + case TrayButton.ReportBug: + Process bugReportProcess = new(); + bugReportProcess.StartInfo = new ProcessStartInfo + { + FileName = "Tools\\PowerToys.BugReportTool.exe", + CreateNoWindow = true, + }; + + bugReportProcess.EnableRaisingEvents = true; + + EnableMenuItem(_trayIconMenu, (uint)TrayButton.ReportBug, 0x000000 | 0x00001); + + bugReportProcess.Exited += (sender, e) => + { + bugReportProcess.Dispose(); + EnableMenuItem(_trayIconMenu, (uint)TrayButton.ReportBug, 0x00000000); + }; + + bugReportProcess.Start(); + + break; + case TrayButton.Close: + Runner.Close(); + break; + } + } + } +} diff --git a/src/RunnerV2/RunnerV2/Models/SpecialMode.cs b/src/RunnerV2/RunnerV2/Models/SpecialMode.cs new file mode 100644 index 0000000000..178a34e4ca --- /dev/null +++ b/src/RunnerV2/RunnerV2/Models/SpecialMode.cs @@ -0,0 +1,14 @@ +// 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. + +namespace RunnerV2.Models +{ + internal enum SpecialMode + { + None, + Win32ToastNotificationCOMServer, + ToastNotificationHandler, + ReportSuccessfulUpdate, + } +} diff --git a/src/RunnerV2/RunnerV2/NativeMethods.cs b/src/RunnerV2/RunnerV2/NativeMethods.cs new file mode 100644 index 0000000000..34b4731345 --- /dev/null +++ b/src/RunnerV2/RunnerV2/NativeMethods.cs @@ -0,0 +1,176 @@ +// 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.Drawing; +using System.Runtime.InteropServices; + +namespace RunnerV2 +{ + internal static partial class NativeMethods + { + [LibraryImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool OpenProcessToken(IntPtr processHandle, uint desiredAccess, out IntPtr tokenHandle); + + [LibraryImport("advapi32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool GetTokenInformation(IntPtr tokenHandle, TOKEN_INFORMATION_CLASS tokenInformationClass, ref TokenElevation tokenInformation, uint tokenInformationLength, out uint returnLength); + + [LibraryImport("Kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool CloseHandle(IntPtr hObject); + + internal enum TOKEN_INFORMATION_CLASS + { + TOKEN_ELEVATION = 20, + } + + [StructLayout(LayoutKind.Sequential)] + internal struct TokenElevation + { + public uint TokenIsElevated; + } + + internal const int TOKENQUERY = 0x0008; + + [LibraryImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); + + [LibraryImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool UnregisterHotKey(IntPtr hWnd, int id); + + [LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool AppendMenuW(IntPtr hMenu, uint uFlags, UIntPtr uIDNewItem, string lpNewItem); + + [LibraryImport("user32.dll", SetLastError = true)] + internal static partial IntPtr CreatePopupMenu(); + + [LibraryImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool SetForegroundWindow(IntPtr hWnd); + + [LibraryImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool TrackPopupMenu(IntPtr hMenu, uint uFlags, int x, int y, int nReserved, IntPtr hWnd, IntPtr prcRect); + + [LibraryImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint uEnable); + + internal const uint NIMADD = 0x00000000; + + internal struct NOTIFYICONDATA + { + public uint CbSize; + public IntPtr HWnd; + public uint UId; + public uint UFlags; + public uint UCallbackMessage; + public IntPtr HIcon; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string SzTip; + public uint DwState; + public uint DwStateMask; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string SzInfo; + public uint UTimeoutOrVersion; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] + public string SzInfoTitle; + public uint DwInfoFlags; + public Guid GuidItem; + public IntPtr HBalloonIcon; + } + + [DllImport("shell32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool Shell_NotifyIcon(uint dwMessage, ref NOTIFYICONDATA lpdata); + + [LibraryImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint msg, uint action, IntPtr pChangeFilterStruct); + + internal const uint CSVREDRAW = 0x0001; + internal const uint CSHREDRAW = 0x0002; + + internal const uint WSOVERLAPPEDWINDOW = 0x00CF0000; + internal const uint WSPOPUP = 0x80000000; + + internal const int CWUSEDEFAULT = unchecked((int)0x80000000); + + internal static readonly IntPtr IDCARROW = new(32512); + + [DllImport("user32.dll")] + internal static extern IntPtr GetMessageW(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool TranslateMessage(ref MSG lpMsg); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + internal static extern bool DispatchMessageW(ref MSG lpMsg); + + internal struct MSG + { + public IntPtr HWnd; + public uint Message; + public UIntPtr WParam; + public long LParam; + public ulong Time; + public Point Pt; + } + + internal enum WindowMessages : uint + { + COMMAND = 0x0111, + HOTKEY = 0x0312, + ICON_NOTIFY = 0x0800, + } + + [DllImport("user32.dll")] + internal static extern ushort RegisterClassW(ref WNDCLASS lpWndClass); + + [LibraryImport("user32.dll", SetLastError = false)] + internal static partial IntPtr DefWindowProcW(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + [LibraryImport("user32.dll", SetLastError = true, StringMarshalling = StringMarshalling.Utf16)] + internal static partial nint CreateWindowExW( + uint dwExStyle, + string lpClassName, + string lpWindowName, + uint dwStyle, + int x, + int y, + int nWidth, + int nHeight, + IntPtr hWndParent, + IntPtr hMenu, + IntPtr hInstance, + IntPtr lpParam); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + internal delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct WNDCLASS + { + public uint Style; + public WndProc LpfnWndProc; + public int CbClsExtra; + public int CbWndExtra; + public IntPtr HInstance; + public IntPtr HIcon; + public IntPtr HCursor; + public IntPtr HbrBackground; + [MarshalAs(UnmanagedType.LPWStr)] + public string LpszMenuName; + [MarshalAs(UnmanagedType.LPWStr)] + public string LpszClassName; + } + } +} diff --git a/src/RunnerV2/RunnerV2/Program.cs b/src/RunnerV2/RunnerV2/Program.cs new file mode 100644 index 0000000000..99c5b0567c --- /dev/null +++ b/src/RunnerV2/RunnerV2/Program.cs @@ -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.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using Microsoft.PowerToys.Settings.UI.Library; +using PowerToys.GPOWrapperProjection; +using RunnerV2; +using RunnerV2.Helpers; +using RunnerV2.Models; +using Settings.UI.Library; + +internal sealed class Program +{ + private static readonly SettingsUtils _settingsUtils = new(); + private static GeneralSettings _generalSettings = _settingsUtils.GetSettings(); + + public static GeneralSettings GeneralSettings => _generalSettings; + + private static void Main(string[] args) + { + switch (ShouldRunInSpecialMode(args)) + { + case SpecialMode.None: + break; + default: + throw new NotImplementedException("Special modes are not implemented yet."); + } + + bool shouldOpenSettings = args.Any(s => s.StartsWith("--open-settings", StringComparison.InvariantCulture)); + bool shouldOpenSettingsToSpecificPage = args.Any(s => s.StartsWith("--open-settings=", StringComparison.InvariantCulture)); + + // Check if PowerToys is already running + if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1) + { + throw new NotImplementedException("Opening another instance window is not supported yet."); + } + + /* + * Todo: Data diagnotics + */ + + bool isElevated = ElevationHelper.IsProcessElevated(); + bool hasDontElevateArgument = args.Contains("--dont-elevate"); + 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(fileName: "last_version_run.json").LastVersion && (!_generalSettings.ShowWhatsNewAfterUpdates || GPOWrapper.GetDisableShowWhatsNewAfterUpdatesValue() != GpoRuleConfigured.Disabled)) + { + afterInitializationAction += () => + { + SettingsHelper.OpenSettingsWindow(showScoobeWindow: true); + }; + } + + if (!_settingsUtils.GetSettings(fileName: "oobe_settings.json").OpenedAtFirstLaunch) + { + afterInitializationAction += () => + { + SettingsHelper.OpenSettingsWindow(showOobeWindow: true); + }; + } + + // Set last version run + _settingsUtils.SaveSettings(new LastVersionRunSettings() { LastVersion = $"v{version.Major}.{version.Minor}.{version.Build}" }.ToJsonString(), fileName: "last_version_run.json"); + + switch ((isElevated, hasDontElevateArgument, runElevatedSetting, hasRestartedElevatedArgment)) + { + case (true, true, false, _): + // Todo: Scheudle restart as non elevated + throw new NotImplementedException(); + case (true, _, _, _): + case (_, _, false, _): + case (_, true, _, _): + case (false, _, _, true): + _ = Runner.Run(afterInitializationAction); + + // Todo: Save settings + break; + default: + // Todo: scheudle restart as elevated + throw new NotImplementedException(); + } + } + + private static SpecialMode ShouldRunInSpecialMode(string[] args) + { + // TODO + return SpecialMode.None; + } +} diff --git a/src/RunnerV2/RunnerV2/Runner.cs b/src/RunnerV2/RunnerV2/Runner.cs new file mode 100644 index 0000000000..d0b7b48a7c --- /dev/null +++ b/src/RunnerV2/RunnerV2/Runner.cs @@ -0,0 +1,212 @@ +// 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.Frozen; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows.Forms; +using ManagedCommon; +using RunnerV2.Helpers; +using static RunnerV2.NativeMethods; + +namespace RunnerV2 +{ + internal static partial class Runner + { + public static nint RunnerHwnd { get; private set; } + + private const string TrayWindowClassName = "pt_tray_icon_window_class"; + + static Runner() + { + InitializeTrayWindow(); + } + + private static List _successfullyAddedModules = []; + + public static List LoadedModules => _successfullyAddedModules; + + internal static bool Run(Action afterInitializationAction) + { + // Todo: Start tray icon + TrayIconManager.StartTrayIcon(); + FrozenSet modulesToLoad = ["PowerToys.AlwaysOnTopModuleInterface.dll", "WinUI3Apps\\PowerToys.Hosts.dll"]; + + List failedModuleLoads = []; + + foreach (string module in modulesToLoad) + { + try + { + Assembly moduleAssembly = Assembly.LoadFrom(Path.GetFullPath(module)); + Type moduleInterfaceType = moduleAssembly.GetTypes().First(t => t.GetInterfaces().Any(i => i.Name.StartsWith(typeof(IPowerToysModule).Name, StringComparison.InvariantCulture))); + _successfullyAddedModules.Add((IPowerToysModule)Activator.CreateInstance(moduleInterfaceType)!); + } + catch (Exception e) + { + failedModuleLoads.Add(module); + Console.WriteLine($"Failed to load module {module}: {e.Message}"); + } + } + + if (failedModuleLoads.Count > 0) + { + MessageBox.Show("The following modules failed to load: \n- " + string.Join("\n- ", failedModuleLoads), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + foreach (IPowerToysModule module in _successfullyAddedModules) + { + ToggleModuleStateBasedOnEnabledProperty(module); + } + + afterInitializationAction(); + MessageLoop(); + + return true; + } + + private static void MessageLoop() + { + while (true) + { + if (GetMessageW(out MSG msg, IntPtr.Zero, 0, 0) != 0) + { + TranslateMessage(ref msg); + DispatchMessageW(ref msg); + + switch (msg.Message) + { + case (uint)WindowMessages.HOTKEY: + HotkeyManager.ProcessHotkey(msg.WParam); + break; + case (uint)WindowMessages.ICON_NOTIFY: + TrayIconManager.ProcessTrayIconMessage(msg.LParam); + break; + case (uint)WindowMessages.COMMAND: + TrayIconManager.ProcessTrayMenuCommand(msg.WParam); + break; + default: + break; + } + } + } + } + + [DoesNotReturn] + internal static void Close() + { + foreach (IPowerToysModule module in _successfullyAddedModules) + { + try + { + module.Disable(); + if (module.HotkeyEx is not null) + { + HotkeyManager.DisableHotkey(module.HotkeyEx); + } + } + catch (Exception e) + { + MessageBox.Show($"The module {module.Name} failed to unload: \n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + Environment.Exit(0); + } + + public static void ToggleModuleStateBasedOnEnabledProperty(IPowerToysModule module) + { + if ((module.Enabled && (module.GpoRuleConfigured != PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)) || module.GpoRuleConfigured == PowerToys.GPOWrapper.GpoRuleConfigured.Enabled) + { + try + { + module.Enable(); + + /* Todo: conflict manager */ + + if (module.HotkeyEx is not null) + { + HotkeyManager.EnableHotkey(module.HotkeyEx, module.OnHotkey); + } + } + catch (Exception e) + { + MessageBox.Show($"The module {module.Name} failed to load: \n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + return; + } + + try + { + module.Disable(); + + if (module.HotkeyEx is not null) + { + HotkeyManager.DisableHotkey(module.HotkeyEx); + } + } + catch (Exception e) + { + MessageBox.Show($"The module {module.Name} failed to unload: \n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private static void InitializeTrayWindow() + { + IntPtr hInstance = Process.GetCurrentProcess().MainModule!.BaseAddress; + IntPtr hCursor = Cursors.Arrow.Handle; + IntPtr hIcon = SystemIcons.Application.Handle; + + var wc = new WNDCLASS + { + HCursor = hCursor, + HInstance = hInstance, + LpszClassName = TrayWindowClassName, + Style = CSHREDRAW | CSVREDRAW, + LpfnWndProc = TrayIconWindowProc, + HIcon = hIcon, + HbrBackground = IntPtr.Zero, + LpszMenuName = string.Empty, + CbClsExtra = 0, + CbWndExtra = 0, + }; + + _ = RegisterClassW(ref wc); + + RunnerHwnd = CreateWindowExW( + 0, + wc.LpszClassName, + TrayWindowClassName, + WSOVERLAPPEDWINDOW | WSPOPUP, + CWUSEDEFAULT, + CWUSEDEFAULT, + CWUSEDEFAULT, + CWUSEDEFAULT, + IntPtr.Zero, + IntPtr.Zero, + wc.HInstance, + IntPtr.Zero); + + if (RunnerHwnd == IntPtr.Zero) + { + var err = Marshal.GetLastPInvokeError(); + MessageBox.Show($"CreateWindowExW failed. LastError={err}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private static IntPtr TrayIconWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + { + TrayIconManager.ProcessTrayIconMessage(lParam.ToInt64()); + return DefWindowProcW(hWnd, msg, wParam, lParam); + } + } +} diff --git a/src/RunnerV2/RunnerV2/RunnerV2.csproj b/src/RunnerV2/RunnerV2/RunnerV2.csproj new file mode 100644 index 0000000000..f8ea6d2596 --- /dev/null +++ b/src/RunnerV2/RunnerV2/RunnerV2.csproj @@ -0,0 +1,20 @@ + + + + + WinExe + PowerToys Runner + PowerToys2 + ..\..\..\$(Platform)\$(Configuration) + enable + false + false + icon.ico + app.manifest + + + + + + + diff --git a/src/RunnerV2/RunnerV2/app.manifest b/src/RunnerV2/RunnerV2/app.manifest new file mode 100644 index 0000000000..8d3ce52af3 --- /dev/null +++ b/src/RunnerV2/RunnerV2/app.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + true/PM + PerMonitorV2 + + + diff --git a/src/RunnerV2/RunnerV2/icon.ico b/src/RunnerV2/RunnerV2/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..6cbba351a112cc958f19c4db3bb8bd90c68cc74f GIT binary patch literal 53114 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 ?VJPSV#OqUiqkY5bCqxZ#V;BUIp0M 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 null; + + public virtual Action OnHotkey => () => { }; + + public virtual Action OnSettingsChanged(string settingsKind, JsonElement jsonProperties) => () => { }; + } +} diff --git a/src/common/ManagedCommon/LanguageHelper.cs b/src/common/ManagedCommon/LanguageHelper.cs index 89b48e7ccb..b3a52722ed 100644 --- a/src/common/ManagedCommon/LanguageHelper.cs +++ b/src/common/ManagedCommon/LanguageHelper.cs @@ -18,7 +18,7 @@ namespace ManagedCommon internal sealed class OutGoingLanguageSettings { [JsonPropertyName("language")] - public string LanguageTag { get; set; } + public string? LanguageTag { get; set; } } public static string LoadLanguage() @@ -36,7 +36,7 @@ namespace ManagedCommon inputStream.Close(); reader.Dispose(); - return JsonSerializer.Deserialize(data, SourceGenerationContext.Default.OutGoingLanguageSettings).LanguageTag; + return JsonSerializer.Deserialize(data, SourceGenerationContext.Default.OutGoingLanguageSettings)!.LanguageTag!; } catch (Exception) { diff --git a/src/common/ManagedCommon/Logger.cs b/src/common/ManagedCommon/Logger.cs index 1173920340..22af2c560d 100644 --- a/src/common/ManagedCommon/Logger.cs +++ b/src/common/ManagedCommon/Logger.cs @@ -29,12 +29,12 @@ namespace ManagedCommon /// /// Gets the path to the log directory for the current version of the app. /// - public static string CurrentVersionLogDirectoryPath { get; private set; } + public static string? CurrentVersionLogDirectoryPath { get; private set; } /// /// Gets the path to the log directory for the app. /// - public static string AppLogDirectoryPath { get; private set; } + public static string? AppLogDirectoryPath { get; private set; } /// /// Initializes the logger and sets the path for logging. @@ -45,7 +45,7 @@ namespace ManagedCommon public static void InitializeLogger(string applicationLogPath, bool isLocalLow = false) { string versionedPath = LogDirectoryPath(applicationLogPath, isLocalLow); - string basePath = Path.GetDirectoryName(versionedPath); + string basePath = Path.GetDirectoryName(versionedPath)!; if (!Directory.Exists(versionedPath)) { diff --git a/src/common/ManagedCommon/ManagedCommon.csproj b/src/common/ManagedCommon/ManagedCommon.csproj index bd74253073..8be6b9bb5f 100644 --- a/src/common/ManagedCommon/ManagedCommon.csproj +++ b/src/common/ManagedCommon/ManagedCommon.csproj @@ -6,6 +6,7 @@ PowerToys ManagedCommon PowerToys.ManagedCommon + enable @@ -20,6 +21,7 @@ + diff --git a/src/common/ManagedCommon/ThemeHelpers.cs b/src/common/ManagedCommon/ThemeHelpers.cs index 181b3dbbc3..cfc332963c 100644 --- a/src/common/ManagedCommon/ThemeHelpers.cs +++ b/src/common/ManagedCommon/ThemeHelpers.cs @@ -24,7 +24,7 @@ namespace ManagedCommon // based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application public static AppTheme GetAppTheme() { - int value = (int)Registry.GetValue($"{HKeyRoot}\\{HkeyWindowsPersonalizeTheme}", HValueAppTheme, 1); + int value = (int)Registry.GetValue($"{HKeyRoot}\\{HkeyWindowsPersonalizeTheme}", HValueAppTheme, 1)!; return (AppTheme)value; } diff --git a/src/common/ManagedCommon/ThemeListener.cs b/src/common/ManagedCommon/ThemeListener.cs index 945ab37deb..635d327452 100644 --- a/src/common/ManagedCommon/ThemeListener.cs +++ b/src/common/ManagedCommon/ThemeListener.cs @@ -24,7 +24,7 @@ namespace ManagedCommon /// /// An event that fires if the Theme changes. /// - public event ThemeChangedEvent ThemeChanged; + public event ThemeChangedEvent? ThemeChanged; private readonly ManagementEventWatcher watcher; @@ -33,7 +33,7 @@ namespace ManagedCommon var currentUser = WindowsIdentity.GetCurrent(); var query = new WqlEventQuery( $"SELECT * FROM RegistryValueChangeEvent WHERE Hive='HKEY_USERS' AND " + - $"KeyPath='{currentUser.User.Value}\\\\{ThemeHelpers.HkeyWindowsPersonalizeTheme.Replace("\\", "\\\\")}' AND ValueName='{ThemeHelpers.HValueAppTheme}'"); + $"KeyPath='{currentUser.User?.Value}\\\\{ThemeHelpers.HkeyWindowsPersonalizeTheme.Replace("\\", "\\\\")}' AND ValueName='{ThemeHelpers.HValueAppTheme}'"); watcher = new ManagementEventWatcher(query); watcher.EventArrived += Watcher_EventArrived; watcher.Start(); diff --git a/src/modules/Hosts/Hosts/Hosts.csproj b/src/modules/Hosts/Hosts/Hosts.csproj index cf595dd44b..b979a7604c 100644 --- a/src/modules/Hosts/Hosts/Hosts.csproj +++ b/src/modules/Hosts/Hosts/Hosts.csproj @@ -52,13 +52,6 @@ - - - PowerToys.GPOWrapper - $(OutDir) - false - - @@ -83,7 +76,7 @@ - + diff --git a/src/modules/Hosts/Hosts/ModuleInterface.cs b/src/modules/Hosts/Hosts/ModuleInterface.cs new file mode 100644 index 0000000000..d19bb88775 --- /dev/null +++ b/src/modules/Hosts/Hosts/ModuleInterface.cs @@ -0,0 +1,34 @@ +// 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.Diagnostics; +using System.IO; +using System.Reflection; +using ManagedCommon; +using Microsoft.PowerToys.Settings.UI.Library; +using PowerToys.GPOWrapper; + +namespace Hosts +{ + internal sealed class ModuleInterface : IPowerToysModule + { + public bool Enabled => new SettingsUtils().GetSettingsOrDefault().Enabled.Hosts; + + public GpoRuleConfigured GpoRuleConfigured => GpoRuleConfigured.NotConfigured; + + public string Name => "Hosts"; + + public void Disable() + { + foreach (var process in Process.GetProcessesByName("PowerToys.Hosts.exe")) + { + process.Kill(); + } + } + + public void Enable() + { + } + } +} diff --git a/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.base.rc b/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.base.rc deleted file mode 100644 index 5fa3c8b90d..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.base.rc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "resource.h" -#include "../../../common/version/version.h" - -#define APSTUDIO_READONLY_SYMBOLS -#include "winres.h" -#undef APSTUDIO_READONLY_SYMBOLS - -1 VERSIONINFO -FILEVERSION FILE_VERSION -PRODUCTVERSION PRODUCT_VERSION -FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG -FILEFLAGS VS_FF_DEBUG -#else -FILEFLAGS 0x0L -#endif -FILEOS VOS_NT_WINDOWS32 -FILETYPE VFT_DLL -FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset - BEGIN - VALUE "CompanyName", COMPANY_NAME - VALUE "FileDescription", FILE_DESCRIPTION - VALUE "FileVersion", FILE_VERSION_STRING - VALUE "InternalName", INTERNAL_NAME - VALUE "LegalCopyright", COPYRIGHT_NOTE - VALUE "OriginalFilename", ORIGINAL_FILENAME - VALUE "ProductName", PRODUCT_NAME - VALUE "ProductVersion", PRODUCT_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset - END -END diff --git a/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj b/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj deleted file mode 100644 index f74481f2e0..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - 16.0 - {B41B888C-7DB8-4747-B262-4062E05A230D} - Win32Proj - HostsModuleInterface - HostsModuleInterface - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - ..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\ - PowerToys.HostsModuleInterface - - - true - - - false - - - - ..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories) - - - - - - - - - - - - - Create - - - - - - {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} - - - {6955446d-23f7-4023-9bb3-8657f904af99} - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj.filters b/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj.filters deleted file mode 100644 index 004a9a4d07..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/HostsModuleInterface.vcxproj.filters +++ /dev/null @@ -1,59 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {875a08c6-f610-4667-bd0f-80171ed96072} - - - - - Source Files - - - Source Files - - - Source Files - - - - - Resource Files - - - Resource Files - - - Header Files - - - - - - Header Files - - - Generated Files - - - Header Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/src/modules/Hosts/HostsModuleInterface/Resource.resx b/src/modules/Hosts/HostsModuleInterface/Resource.resx deleted file mode 100644 index d0309bf10f..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/Resource.resx +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Hosts File Editor - "Hosts" refer to the system hosts file, do not loc - - \ No newline at end of file diff --git a/src/modules/Hosts/HostsModuleInterface/dllmain.cpp b/src/modules/Hosts/HostsModuleInterface/dllmain.cpp deleted file mode 100644 index 993226ac2b..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/dllmain.cpp +++ /dev/null @@ -1,300 +0,0 @@ -#include "pch.h" - -#include "trace.h" -#include -#include -#include -#include "Generated Files/resource.h" - -#include -#include -#include -#include -#include -#include -#include - -extern "C" IMAGE_DOS_HEADER __ImageBase; - -BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - Trace::RegisterProvider(); - break; - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - case DLL_PROCESS_DETACH: - Trace::UnregisterProvider(); - break; - } - return TRUE; -} - -namespace -{ - // Name of the powertoy module. - inline const std::wstring ModuleKey = L"Hosts"; -} - -class HostsModuleInterface : public PowertoyModuleIface -{ -private: - bool m_enabled = false; - - std::wstring app_name; - - //contains the non localized key of the powertoy - std::wstring app_key; - - HANDLE m_hProcess = nullptr; - - HANDLE m_hShowEvent{}; - - HANDLE m_hShowAdminEvent{}; - - HANDLE m_hTerminateEvent{}; - - bool is_process_running() - { - return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT; - } - - void bring_process_to_front() - { - auto enum_windows = [](HWND hwnd, LPARAM param) -> BOOL { - HANDLE process_handle = reinterpret_cast(param); - DWORD window_process_id = 0; - - GetWindowThreadProcessId(hwnd, &window_process_id); - if (GetProcessId(process_handle) == window_process_id) - { - SetForegroundWindow(hwnd); - return FALSE; - } - return TRUE; - }; - - EnumWindows(enum_windows, (LPARAM)m_hProcess); - } - - void launch_process(bool runas) - { - Logger::trace(L"Starting Hosts process"); - unsigned long powertoys_pid = GetCurrentProcessId(); - - std::wstring executable_args = L""; - executable_args.append(std::to_wstring(powertoys_pid)); - - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; - sei.lpFile = L"WinUI3Apps\\PowerToys.Hosts.exe"; - sei.nShow = SW_SHOWNORMAL; - sei.lpParameters = executable_args.data(); - - if (runas) - { - sei.lpVerb = L"runas"; - } - - if (ShellExecuteExW(&sei)) - { - Logger::trace("Successfully started the Hosts process"); - } - else - { - Logger::error(L"Hosts failed to start. {}", get_last_error_or_default(GetLastError())); - } - - m_hProcess = sei.hProcess; - } - -public: - EventWaiter m_showEventWaiter; - - EventWaiter m_showAdminEventWaiter; - - HostsModuleInterface() - { - app_name = GET_RESOURCE_STRING(IDS_HOSTS_NAME); - app_key = ModuleKey; - LoggerHelpers::init_logger(app_key, L"ModuleInterface", LogSettings::hostsLoggerName); - - m_hShowEvent = CreateDefaultEvent(CommonSharedConstants::SHOW_HOSTS_EVENT); - if (!m_hShowEvent) - { - Logger::error(L"Failed to create show hosts event"); - auto message = get_last_error_message(GetLastError()); - if (message.has_value()) - { - Logger::error(message.value()); - } - } - - m_hShowAdminEvent = CreateDefaultEvent(CommonSharedConstants::SHOW_HOSTS_ADMIN_EVENT); - if (!m_hShowAdminEvent) - { - Logger::error(L"Failed to create show hosts admin event"); - auto message = get_last_error_message(GetLastError()); - if (message.has_value()) - { - Logger::error(message.value()); - } - } - - m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::TERMINATE_HOSTS_EVENT); - if (!m_hTerminateEvent) - { - Logger::error(L"Failed to create terminate hosts event"); - auto message = get_last_error_message(GetLastError()); - if (message.has_value()) - { - Logger::error(message.value()); - } - } - - m_showEventWaiter = EventWaiter(CommonSharedConstants::SHOW_HOSTS_EVENT, [&](int err) - { - if (m_enabled && err == ERROR_SUCCESS) - { - Logger::trace(L"{} event was signaled", CommonSharedConstants::SHOW_HOSTS_EVENT); - - if (is_process_running()) - { - bring_process_to_front(); - } - else - { - launch_process(false); - } - - Trace::ActivateEditor(); - } - }); - - m_showAdminEventWaiter = EventWaiter(CommonSharedConstants::SHOW_HOSTS_ADMIN_EVENT, [&](int err) - { - if (m_enabled && err == ERROR_SUCCESS) - { - Logger::trace(L"{} event was signaled", CommonSharedConstants::SHOW_HOSTS_ADMIN_EVENT); - - if (is_process_running()) - { - bring_process_to_front(); - } - else - { - launch_process(true); - } - - Trace::ActivateEditor(); - } - }); - } - - ~HostsModuleInterface() - { - m_enabled = false; - } - - // Destroy the powertoy and free memory - virtual void destroy() override - { - Logger::trace("HostsModuleInterface::destroy()"); - - if (m_hShowEvent) - { - CloseHandle(m_hShowEvent); - m_hShowEvent = nullptr; - } - - if (m_hShowAdminEvent) - { - CloseHandle(m_hShowAdminEvent); - m_hShowAdminEvent = nullptr; - } - - if (m_hTerminateEvent) - { - CloseHandle(m_hTerminateEvent); - m_hTerminateEvent = nullptr; - } - - delete this; - } - - // Return the localized display name of the powertoy - virtual const wchar_t* get_name() override - { - return app_name.c_str(); - } - - // Return the non localized key of the powertoy, this will be cached by the runner - virtual const wchar_t* get_key() override - { - return app_key.c_str(); - } - - // Return the configured status for the gpo policy for the module - virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override - { - return powertoys_gpo::getConfiguredHostsFileEditorEnabledValue(); - } - - virtual bool get_config(wchar_t* /*buffer*/, int* /*buffer_size*/) override - { - return false; - } - - virtual void call_custom_action(const wchar_t* /*action*/) override - { - } - - virtual void set_config(const wchar_t* /*config*/) override - { - } - - virtual bool is_enabled() override - { - return m_enabled; - } - - virtual void enable() - { - Logger::trace("HostsModuleInterface::enable()"); - m_enabled = true; - Trace::EnableHostsFileEditor(true); - }; - - virtual void disable() - { - Logger::trace("HostsModuleInterface::disable()"); - if (m_enabled) - { - if (m_hShowEvent) - { - ResetEvent(m_hShowEvent); - } - - if (m_hShowAdminEvent) - { - ResetEvent(m_hShowAdminEvent); - } - - SetEvent(m_hTerminateEvent); - WaitForSingleObject(m_hProcess, 1500); - TerminateProcess(m_hProcess, 1); - ResetEvent(m_hTerminateEvent); - } - - m_enabled = false; - Trace::EnableHostsFileEditor(false); - } -}; - -extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() -{ - return new HostsModuleInterface(); -} \ No newline at end of file diff --git a/src/modules/Hosts/HostsModuleInterface/packages.config b/src/modules/Hosts/HostsModuleInterface/packages.config deleted file mode 100644 index 09bfc449e2..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/modules/Hosts/HostsModuleInterface/pch.cpp b/src/modules/Hosts/HostsModuleInterface/pch.cpp deleted file mode 100644 index 1d9f38c57d..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pch.h" diff --git a/src/modules/Hosts/HostsModuleInterface/pch.h b/src/modules/Hosts/HostsModuleInterface/pch.h deleted file mode 100644 index 5cb4cbf823..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/pch.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN -#include diff --git a/src/modules/Hosts/HostsModuleInterface/resource.base.h b/src/modules/Hosts/HostsModuleInterface/resource.base.h deleted file mode 100644 index 4c6a75ef09..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/resource.base.h +++ /dev/null @@ -1,13 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by AlwaysOnTopModuleInterface.rc - -////////////////////////////// -// Non-localizable - -#define FILE_DESCRIPTION "PowerToys Hosts Module" -#define INTERNAL_NAME "PowerToys.HostsModuleInterface" -#define ORIGINAL_FILENAME "PowerToys.HostsModuleInterface.dll" - -// Non-localizable -////////////////////////////// diff --git a/src/modules/Hosts/HostsModuleInterface/trace.cpp b/src/modules/Hosts/HostsModuleInterface/trace.cpp deleted file mode 100644 index 104075a829..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/trace.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "pch.h" -#include "trace.h" - -#include - -TRACELOGGING_DEFINE_PROVIDER( - g_hProvider, - "Microsoft.PowerToys", - // {38e8889b-9731-53f5-e901-e8a7c1753074} - (0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74), - TraceLoggingOptionProjectTelemetry()); - -// Log if the user has HostsFileEditor enabled or disabled -void Trace::EnableHostsFileEditor(const bool enabled) noexcept -{ - TraceLoggingWriteWrapper( - g_hProvider, - "HostsFileEditor_EnableHostsFileEditor", - ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), - TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE), - TraceLoggingBoolean(enabled, "Enabled")); -} - -// Log that the user tried to activate the editor -void Trace::ActivateEditor() noexcept -{ - TraceLoggingWriteWrapper( - g_hProvider, - "HostsFileEditor_Activate", - ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance), - TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE)); -} diff --git a/src/modules/Hosts/HostsModuleInterface/trace.h b/src/modules/Hosts/HostsModuleInterface/trace.h deleted file mode 100644 index f3dc6310b5..0000000000 --- a/src/modules/Hosts/HostsModuleInterface/trace.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -class Trace : public telemetry::TraceBase -{ -public: - // Log if the user has HostsFileEditor enabled or disabled - static void EnableHostsFileEditor(const bool enabled) noexcept; - - // Log that the user tried to activate the editor - static void ActivateEditor() noexcept; -}; diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.csproj b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.csproj new file mode 100644 index 0000000000..bab66629ab --- /dev/null +++ b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.csproj @@ -0,0 +1,18 @@ + + + + + PowerToys Alway on Top module interface + PowerToys.AlwaysOnTopModuleInterface + ..\..\..\..\$(Platform)\$(Configuration) + false + false + enable + + + + + + + + diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.rc b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.rc deleted file mode 100644 index 5fa3c8b90d..0000000000 --- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.rc +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include "resource.h" -#include "../../../common/version/version.h" - -#define APSTUDIO_READONLY_SYMBOLS -#include "winres.h" -#undef APSTUDIO_READONLY_SYMBOLS - -1 VERSIONINFO -FILEVERSION FILE_VERSION -PRODUCTVERSION PRODUCT_VERSION -FILEFLAGSMASK VS_FFI_FILEFLAGSMASK -#ifdef _DEBUG -FILEFLAGS VS_FF_DEBUG -#else -FILEFLAGS 0x0L -#endif -FILEOS VOS_NT_WINDOWS32 -FILETYPE VFT_DLL -FILESUBTYPE VFT2_UNKNOWN -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset - BEGIN - VALUE "CompanyName", COMPANY_NAME - VALUE "FileDescription", FILE_DESCRIPTION - VALUE "FileVersion", FILE_VERSION_STRING - VALUE "InternalName", INTERNAL_NAME - VALUE "LegalCopyright", COPYRIGHT_NOTE - VALUE "OriginalFilename", ORIGINAL_FILENAME - VALUE "ProductName", PRODUCT_NAME - VALUE "ProductVersion", PRODUCT_VERSION_STRING - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset - END -END diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj deleted file mode 100644 index 5f63a0e628..0000000000 --- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj +++ /dev/null @@ -1,82 +0,0 @@ - - - - - 15.0 - {48A0A19E-A0BE-4256-ACF8-CC3B80291AF9} - Win32Proj - alwaysontop - AlwaysOnTopModuleInterface - - - - DynamicLibrary - v143 - - - - - - - - - - - ..\..\..\..\$(Platform)\$(Configuration)\ - - - PowerToys.AlwaysOnTopModuleInterface - - - - _WINDOWS;_USRDLL;%(PreprocessorDefinitions) - ..\;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories) - - - $(OutDir)$(TargetName)$(TargetExt) - gdiplus.lib;dwmapi.lib;shlwapi.lib;uxtheme.lib;shcore.lib;%(AdditionalDependencies) - - - - - - - - - - - - - Create - - - - - {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} - - - {6955446d-23f7-4023-9bb3-8657f904af99} - - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - \ No newline at end of file diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj.filters b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj.filters deleted file mode 100644 index 66fe083d3a..0000000000 --- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/AlwaysOnTopModuleInterface.vcxproj.filters +++ /dev/null @@ -1,53 +0,0 @@ - - - - - Source Files - - - Source Files - - - Source Files - - - - - Header Files - - - Header Files - - - Header Files - - - Resource Files - - - - - {21926bf1-03b3-482d-8f60-8bc4fbfc6564} - - - {2f10207d-d8d1-4a42-8027-8ca597b3cb23} - - - {a4241930-ecae-44e2-be82-25eff2499fcd} - - - {8d479404-964b-4eb1-8fe8-554be3e68c9b} - - - - - - - - Resource Files - - - - - - \ No newline at end of file diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/ModuleInterface.cs b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/ModuleInterface.cs new file mode 100644 index 0000000000..1b3bfb0b19 --- /dev/null +++ b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/ModuleInterface.cs @@ -0,0 +1,72 @@ +// 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.Diagnostics; +using System.Globalization; +using System.Runtime.InteropServices; +using ManagedCommon; +using Microsoft.PowerToys.Settings.UI.Library; +using PowerToys.GPOWrapper; + +namespace AlwaysOnTopModuleInterface +{ + public class ModuleInterface : IPowerToysModule + { + public bool Enabled => true; + + public string Name => "AlwaysOnTop"; + + public GpoRuleConfigured GpoRuleConfigured => GpoRuleConfigured.Unavailable; + + private Process? _process; + + private IntPtr pinEvent = CreateEventW(IntPtr.Zero, false, false, "Local\\AlwaysOnTopPinEvent-892e0aa2-cfa8-4cc4-b196-ddeb32314ce8"); + + public void Disable() + { + if (_process is not null && !_process.HasExited) + { + _process.Kill(); + } + + if (pinEvent != IntPtr.Zero) + { + CloseHandle(pinEvent); + pinEvent = IntPtr.Zero; + } + } + + public void Enable() + { + var psi = new ProcessStartInfo + { + FileName = "PowerToys.AlwaysOnTop.exe", + Arguments = Environment.ProcessId.ToString(CultureInfo.InvariantCulture), + UseShellExecute = true, + }; + + _process = Process.Start(psi); + } + + public HotkeyEx HotkeyEx => new(0x2 | 0x1, 0x54); // Ctrl + Alt + T + + public Action OnHotkey => () => + { + if (_process is not null && !_process.HasExited && pinEvent != IntPtr.Zero) + { + _ = SetEvent(pinEvent); + } + }; + + [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); + } +} diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/dllmain.cpp b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/dllmain.cpp deleted file mode 100644 index 1ed96e79bd..0000000000 --- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/dllmain.cpp +++ /dev/null @@ -1,300 +0,0 @@ -#include "pch.h" - -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - -namespace NonLocalizable -{ - const wchar_t ModulePath[] = L"PowerToys.AlwaysOnTop.exe"; -} - -namespace -{ - const wchar_t JSON_KEY_PROPERTIES[] = L"properties"; - const wchar_t JSON_KEY_WIN[] = L"win"; - const wchar_t JSON_KEY_ALT[] = L"alt"; - const wchar_t JSON_KEY_CTRL[] = L"ctrl"; - const wchar_t JSON_KEY_SHIFT[] = L"shift"; - const wchar_t JSON_KEY_CODE[] = L"code"; - const wchar_t JSON_KEY_HOTKEY[] = L"hotkey"; - const wchar_t JSON_KEY_VALUE[] = L"value"; -} - -BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - Trace::AlwaysOnTop::RegisterProvider(); - break; - - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - - case DLL_PROCESS_DETACH: - Trace::AlwaysOnTop::UnregisterProvider(); - break; - } - return TRUE; -} - -class AlwaysOnTopModuleInterface : public PowertoyModuleIface -{ -public: - // Return the localized display name of the powertoy - virtual PCWSTR get_name() override - { - return app_name.c_str(); - } - - // Return the non localized key of the powertoy, this will be cached by the runner - virtual const wchar_t* get_key() override - { - return app_key.c_str(); - } - - // Return the configured status for the gpo policy for the module - virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override - { - return powertoys_gpo::getConfiguredAlwaysOnTopEnabledValue(); - } - - // Return JSON with the configuration options. - // These are the settings shown on the settings page along with their current values. - virtual bool get_config(wchar_t* buffer, int* buffer_size) override - { - HINSTANCE hinstance = reinterpret_cast(&__ImageBase); - - // Create a Settings object. - PowerToysSettings::Settings settings(hinstance, get_name()); - - return settings.serialize_to_buffer(buffer, buffer_size); - } - - // Passes JSON with the configuration settings for the powertoy. - // This is called when the user hits Save on the settings page. - virtual void set_config(const wchar_t* config) override - { - try - { - // Parse the input JSON string. - PowerToysSettings::PowerToyValues values = - PowerToysSettings::PowerToyValues::from_json_string(config, get_key()); - - parse_hotkey(values); - // If you don't need to do any custom processing of the settings, proceed - // to persists the values calling: - values.save_to_settings_file(); - // Otherwise call a custom function to process the settings before saving them to disk: - // save_settings(); - } - catch (std::exception&) - { - // Improper JSON. - } - } - - virtual bool on_hotkey(size_t /*hotkeyId*/) override - { - if (m_enabled) - { - Logger::trace(L"AlwaysOnTop hotkey pressed"); - if (!is_process_running()) - { - Enable(); - } - - SetEvent(m_hPinEvent); - - return true; - } - - return false; - } - - virtual size_t get_hotkeys(Hotkey* hotkeys, size_t buffer_size) override - { - if (m_hotkey.key) - { - if (hotkeys && buffer_size >= 1) - { - hotkeys[0] = m_hotkey; - } - - return 1; - } - else - { - return 0; - } - } - - // Enable the powertoy - virtual void enable() - { - Logger::info("AlwaysOnTop enabling"); - - Enable(); - } - - // Disable the powertoy - virtual void disable() - { - Logger::info("AlwaysOnTop disabling"); - - Disable(true); - } - - // Returns if the powertoy is enabled - virtual bool is_enabled() override - { - return m_enabled; - } - - // Destroy the powertoy and free memory - virtual void destroy() override - { - Disable(false); - delete this; - } - - AlwaysOnTopModuleInterface() - { - app_name = L"AlwaysOnTop"; //TODO: localize - app_key = NonLocalizable::ModuleKey; - m_hPinEvent = CreateDefaultEvent(CommonSharedConstants::ALWAYS_ON_TOP_PIN_EVENT); - m_hTerminateEvent = CreateDefaultEvent(CommonSharedConstants::ALWAYS_ON_TOP_TERMINATE_EVENT); - init_settings(); - } - -private: - void Enable() - { - m_enabled = true; - - // Log telemetry - Trace::AlwaysOnTop::Enable(true); - - unsigned long powertoys_pid = GetCurrentProcessId(); - std::wstring executable_args = L""; - executable_args.append(std::to_wstring(powertoys_pid)); - ResetEvent(m_hPinEvent); - - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; - sei.lpFile = NonLocalizable::ModulePath; - sei.nShow = SW_SHOWNORMAL; - sei.lpParameters = executable_args.data(); - if (ShellExecuteExW(&sei) == false) - { - Logger::error(L"Failed to start AlwaysOnTop"); - auto message = get_last_error_message(GetLastError()); - if (message.has_value()) - { - Logger::error(message.value()); - } - } - else - { - m_hProcess = sei.hProcess; - } - } - - void Disable(bool const traceEvent) - { - m_enabled = false; - ResetEvent(m_hPinEvent); - - // Log telemetry - if (traceEvent) - { - Trace::AlwaysOnTop::Enable(false); - } - - SetEvent(m_hTerminateEvent); - - // Wait for 1.5 seconds for the process to end correctly and stop etw tracer - WaitForSingleObject(m_hProcess, 1500); - - // If process is still running, terminate it - if (m_hProcess) - { - TerminateProcess(m_hProcess, 0); - m_hProcess = nullptr; - } - } - - void parse_hotkey(PowerToysSettings::PowerToyValues& settings) - { - auto settingsObject = settings.get_raw_json(); - if (settingsObject.GetView().Size()) - { - try - { - auto jsonHotkeyObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HOTKEY).GetNamedObject(JSON_KEY_VALUE); - m_hotkey.win = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_WIN); - m_hotkey.alt = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_ALT); - m_hotkey.shift = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_SHIFT); - m_hotkey.ctrl = jsonHotkeyObject.GetNamedBoolean(JSON_KEY_CTRL); - m_hotkey.key = static_cast(jsonHotkeyObject.GetNamedNumber(JSON_KEY_CODE)); - } - catch (...) - { - Logger::error("Failed to initialize AlwaysOnTop start shortcut"); - } - } - else - { - Logger::info("AlwaysOnTop settings are empty"); - } - } - - bool is_process_running() - { - return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT; - } - - void init_settings() - { - try - { - // Load and parse the settings file for this PowerToy. - PowerToysSettings::PowerToyValues settings = - PowerToysSettings::PowerToyValues::load_from_settings_file(get_key()); - - parse_hotkey(settings); - } - catch (std::exception&) - { - Logger::warn(L"An exception occurred while loading the settings file"); - // Error while loading from the settings file. Let default values stay as they are. - } - } - - std::wstring app_name; - std::wstring app_key; //contains the non localized key of the powertoy - - bool m_enabled = false; - HANDLE m_hProcess = nullptr; - Hotkey m_hotkey; - - // Handle to event used to pin/unpin windows - HANDLE m_hPinEvent; - HANDLE m_hTerminateEvent; -}; - -extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() -{ - return new AlwaysOnTopModuleInterface(); -} diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/packages.config b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/packages.config deleted file mode 100644 index ff4b059648..0000000000 --- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.cpp b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.cpp deleted file mode 100644 index 1d9f38c57d..0000000000 --- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pch.h" diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.h b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.h deleted file mode 100644 index 9dc1f70972..0000000000 --- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/pch.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -#include -#include -#include -#include -#include -#include diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/resource.h b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/resource.h deleted file mode 100644 index a4f258c95b..0000000000 --- a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/resource.h +++ /dev/null @@ -1,13 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by AlwaysOnTopModuleInterface.rc - -////////////////////////////// -// Non-localizable - -#define FILE_DESCRIPTION "PowerToys AlwaysOnTop Module" -#define INTERNAL_NAME "PowerToys.AlwaysOnTopModuleInterface" -#define ORIGINAL_FILENAME "PowerToys.AlwaysOnTopModuleInterface.dll" - -// Non-localizable -////////////////////////////// diff --git a/src/modules/alwaysontop/AlwaysOnTopModuleInterface/targetver.h b/src/modules/alwaysontop/AlwaysOnTopModuleInterface/targetver.h deleted file mode 100644 index 567cd346efccbe2d1f43a4056bdcb58a2b93e1a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 630 zcmaiyOKZYV5QWcL=zj>fEfw0WxN;+co0fK2Vs4B9U*sm0{`t1wOo&Foy0~*EXI^K{ z&F{}p2USW{Xp2p>*G`#oJ!s%(q!H-M(Ty4fmG}kNtEQTB%)V1m=}BwwfWPvrT#@e@ zH0NG}74Ao{glS)#QXA|NYdIfY7hrMp+Ji@H`t9kzWx_SD6;~Ri;cvXH)6CO{-I1p_IJPQ#X=r zigZeSqQguJz35q;zt9^Q_C^^>*mmuXUCp&pw^fPoGX+dho4RCrySs7j@9_UipWkA5 OQDt4mH~x-^Z~X_?9czaG diff --git a/src/settings-ui/Settings.UI.Library/LastVersionRunSettings.cs b/src/settings-ui/Settings.UI.Library/LastVersionRunSettings.cs new file mode 100644 index 0000000000..879e80725d --- /dev/null +++ b/src/settings-ui/Settings.UI.Library/LastVersionRunSettings.cs @@ -0,0 +1,32 @@ +// 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.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Library.Interfaces; + +namespace Settings.UI.Library +{ + public class LastVersionRunSettings : ISettingsConfig + { + [JsonPropertyName("last_version")] + public string LastVersion { get; set; } + + public string GetModuleName() + { + return "LastVersionRun"; + } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + + public bool UpgradeSettingsConfiguration() + { + return false; + } + } +} diff --git a/src/settings-ui/Settings.UI.Library/OOBESettings.cs b/src/settings-ui/Settings.UI.Library/OOBESettings.cs new file mode 100644 index 0000000000..99f90f11d9 --- /dev/null +++ b/src/settings-ui/Settings.UI.Library/OOBESettings.cs @@ -0,0 +1,32 @@ +// 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.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Library.Interfaces; + +namespace Settings.UI.Library +{ + public class OOBESettings : ISettingsConfig + { + [JsonPropertyName("openedAtFirstLaunch")] + public bool OpenedAtFirstLaunch { get; set; } + + public string GetModuleName() + { + return "OOBE"; + } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + + public bool UpgradeSettingsConfiguration() + { + return false; + } + } +} diff --git a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj index 057413a408..f9395ec05f 100644 --- a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj +++ b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj @@ -44,7 +44,7 @@ - PowerToys.GPOWrapper;PowerToys.ZoomItSettingsInterop + PowerToys.ZoomItSettingsInterop $(OutDir) false @@ -113,7 +113,7 @@ - +