diff --git a/src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs b/src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs index 2c277b84ae..656a4d47d3 100644 --- a/src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs +++ b/src/RunnerV2/RunnerV2/Helpers/PackageHelper.cs @@ -72,7 +72,13 @@ namespace RunnerV2.Helpers return [.. matchedFiles]; } - internal static bool RegisterPackage(string packagePath, string[] dependencies) + /// + /// Installs the specified appx package along with its dependencies. + /// + /// Path to the package + /// Array of dependency package paths + /// True if the installation was successful, false otherwise + internal static bool InstallPackage(string packagePath, string[] dependencies) { Logger.LogInfo("Starting package install of package \"" + packagePath + "\""); PackageManager packageManager = new(); @@ -129,6 +135,11 @@ namespace RunnerV2.Helpers return false; } + /// + /// Checks if the package specified by the given path is already installed and satisfies the required version. + /// + /// Path to the package. + /// True if the package is already installed and satisfies the required version, false otherwise. private static bool IsPackageSatisfied(string packagePath) { if (!GetPackageNameAndVersionFromAppx(packagePath, out string name, out PackageVersion version)) @@ -153,6 +164,13 @@ namespace RunnerV2.Helpers return false; } + /// + /// Gets the package name and version from the specified appx package file. + /// + /// Path to the package file. + /// Output parameter for the package name. + /// Output parameter for the package version. + /// True if the package name and version were successfully retrieved, false otherwise. private static bool GetPackageNameAndVersionFromAppx(string packagePath, out string name, out PackageVersion packageVersion) { // Todo: Implement this without interop if possible diff --git a/src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs b/src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs index 072d2b4ba6..d01e3997d3 100644 --- a/src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs +++ b/src/RunnerV2/RunnerV2/Helpers/SettingsHelper.cs @@ -10,16 +10,17 @@ using System.IO; using System.IO.Pipelines; using System.Linq; using System.Text.Json; -using System.Threading; using ManagedCommon; using Microsoft.PowerToys.Settings.UI.Library; using PowerToys.Interop; using RunnerV2.ModuleInterfaces; using Update; -using Windows.Media.Devices; namespace RunnerV2.Helpers { + /// + /// This class provides helper methods to interact with the PowerToys Settings window. + /// internal static class SettingsHelper { private static readonly SettingsUtils _settingsUtils = new(); diff --git a/src/RunnerV2/RunnerV2/ModuleInterfaces/CommandPaletteModuleInterface.cs b/src/RunnerV2/RunnerV2/ModuleInterfaces/CommandPaletteModuleInterface.cs index 67d5037832..796ea662a8 100644 --- a/src/RunnerV2/RunnerV2/ModuleInterfaces/CommandPaletteModuleInterface.cs +++ b/src/RunnerV2/RunnerV2/ModuleInterfaces/CommandPaletteModuleInterface.cs @@ -59,7 +59,7 @@ namespace RunnerV2.ModuleInterfaces if (msixFiles.Length > 0) { - if (!PackageHelper.RegisterPackage(msixFiles[0], dependencies)) + if (!PackageHelper.InstallPackage(msixFiles[0], dependencies)) { Logger.LogError("Failed to register Command Palette package."); } diff --git a/src/RunnerV2/RunnerV2/ModuleInterfaces/ProcessModuleAbstractClass.cs b/src/RunnerV2/RunnerV2/ModuleInterfaces/ProcessModuleAbstractClass.cs index e6846277c8..d2fc35949f 100644 --- a/src/RunnerV2/RunnerV2/ModuleInterfaces/ProcessModuleAbstractClass.cs +++ b/src/RunnerV2/RunnerV2/ModuleInterfaces/ProcessModuleAbstractClass.cs @@ -15,6 +15,9 @@ using RunnerV2.Helpers; namespace RunnerV2.ModuleInterfaces { + /// + /// Base abstract class for modules that launch and manage external processes. + /// internal abstract class ProcessModuleAbstractClass { /// @@ -55,14 +58,36 @@ namespace RunnerV2.ModuleInterfaces NeverExit = 32, } + /// + /// Gets the relative or absolute path to the process executable. + /// public abstract string ProcessPath { get; } + /// + /// Gets the name of the process without the .exe extension. + /// + /// + /// Has no effect if the has the flag set. + /// public abstract string ProcessName { get; } + /// + /// Gets the arguments to pass to the process on launch. + /// + /// + /// If not overridden, no arguments are passed. + /// If the has the flag is set, the runner process ID is prepended to these arguments. + /// public virtual string ProcessArguments { get; } = string.Empty; + /// + /// Gets the options used to configure how the process is launched. + /// public abstract ProcessLaunchOptions LaunchOptions { get; } + /// + /// Ensures that atleast one process is launched. If the process is already running, does nothing. + /// public void EnsureLaunched() { Process[] processes = Process.GetProcessesByName(ProcessName); @@ -74,6 +99,10 @@ namespace RunnerV2.ModuleInterfaces LaunchProcess(); } + /// + /// Launches the process with the specified options. + /// + /// Specifies if the class is currently calling this function as part of a module startup public void LaunchProcess(bool isModuleEnableProcess = false) { if (isModuleEnableProcess && LaunchOptions.HasFlag(ProcessLaunchOptions.SupressLaunchOnModuleEnabled)) @@ -101,14 +130,20 @@ namespace RunnerV2.ModuleInterfaces }); } - public void ProcessExit(int msDelay = 500) + /// + /// Schedules all processes with the specified . + /// + /// + /// If the has the flag set, this function does nothing. + /// + public void ProcessExit() { if (LaunchOptions.HasFlag(ProcessLaunchOptions.NeverExit)) { return; } - ProcessHelper.ScheudleProcessKill(ProcessName, msDelay); + ProcessHelper.ScheudleProcessKill(ProcessName); } } } diff --git a/src/RunnerV2/RunnerV2/NativeMethods.cs b/src/RunnerV2/RunnerV2/NativeMethods.cs index bbc0def459..ca4d910162 100644 --- a/src/RunnerV2/RunnerV2/NativeMethods.cs +++ b/src/RunnerV2/RunnerV2/NativeMethods.cs @@ -190,11 +190,6 @@ namespace RunnerV2 public string LpszClassName; } - [DllImport("user32.dll", SetLastError = true)] - internal static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); - - internal delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); - [DllImport("Advapi32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool ConvertStringSecurityDescriptorToSecurityDescriptorW( @@ -233,22 +228,6 @@ namespace RunnerV2 [DllImport("user32.dll")] internal static extern uint SendInput(uint nInputs, NativeKeyboardHelper.INPUT[] pInputs, int cbSize); - public const int COINIT_MULTITHREADED = 0x0; - - [LibraryImport("ole32.dll")] - public static partial int CoInitializeEx(IntPtr pvReserved, int dwCoInit); - - [LibraryImport("ole32.dll")] - public static partial void CoUninitialize(); - - [DllImport("Shlwapi.dll")] - public static extern IntPtr SHCreateStreamOnFileEx( - [MarshalAs(UnmanagedType.LPWStr)] string pszFile, - uint grfMode, - [MarshalAs(UnmanagedType.Bool)]bool fCreate, - IntPtr pstmTemplate, - out IStream stream); - [DllImport("PowerToys.Interop.dll", CallingConvention = CallingConvention.Cdecl)] internal static extern bool GetPackageNameAndVersionFromAppx( [MarshalAs(UnmanagedType.LPWStr)] string appxPath, diff --git a/src/RunnerV2/RunnerV2/Program.cs b/src/RunnerV2/RunnerV2/Program.cs index 1444e2ef90..43f1899b2e 100644 --- a/src/RunnerV2/RunnerV2/Program.cs +++ b/src/RunnerV2/RunnerV2/Program.cs @@ -111,7 +111,7 @@ internal sealed class Program tempGeneralSettings.IsElevated = isElevated; _settingsUtils.SaveSettings(tempGeneralSettings.ToJsonString()); - _ = Runner.Run(afterInitializationAction); + Runner.Run(afterInitializationAction); break; default: ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevated; @@ -121,6 +121,11 @@ internal sealed class Program ElevationHelper.RestartIfScheudled(); } + /// + /// Returns whether the application should run in a special mode based on the provided arguments. + /// + /// The arguments passed to + /// The the app should run in. private static SpecialMode ShouldRunInSpecialMode(string[] args) { if (args.Length > 0 && args[0].StartsWith("powertoys://", StringComparison.InvariantCultureIgnoreCase)) @@ -137,6 +142,9 @@ internal sealed class Program return SpecialMode.None; } + /// + /// Starts the update process for PowerToys. + /// private static void UpdateNow() { Process.Start(new ProcessStartInfo() diff --git a/src/RunnerV2/RunnerV2/Runner.cs b/src/RunnerV2/RunnerV2/Runner.cs index 1f765e3f07..ea72e9006e 100644 --- a/src/RunnerV2/RunnerV2/Runner.cs +++ b/src/RunnerV2/RunnerV2/Runner.cs @@ -27,12 +27,21 @@ namespace RunnerV2 { internal static partial class Runner { + /// + /// Gets the window handle for the Runner main window that hosts the tray icon and receives system messages. + /// public static nint RunnerHwnd { get; private set; } private const string TrayWindowClassName = "pt_tray_icon_window_class"; + /// + /// Gets all the currently loaded modules. + /// public static List LoadedModules { get; } = []; + /// + /// Gets the list of all available PowerToys modules. + /// public static FrozenSet ModulesToLoad { get; } = [ new ColorPickerModuleInterface(), @@ -46,7 +55,11 @@ namespace RunnerV2 new CropAndLockModuleInterface(), ]; - internal static bool Run(Action afterInitializationAction) + /// + /// Runs the main message loop for Runner. + /// + /// A function to execute after initialization. + internal static void Run(Action afterInitializationAction) { Logger.LogInfo("Runner started"); @@ -65,12 +78,13 @@ namespace RunnerV2 afterInitializationAction(); MessageLoop(); - - return true; } private static readonly uint _taskbarCreatedMessage = RegisterWindowMessageW("TaskbarCreated"); + /// + /// The main message loop that processes Windows messages. + /// [STAThread] private static void MessageLoop() { @@ -91,6 +105,9 @@ namespace RunnerV2 Close(); } + /// + /// Closes Runner and all loaded modules. + /// [DoesNotReturn] internal static void Close() { @@ -123,6 +140,10 @@ namespace RunnerV2 Environment.Exit(0); } + /// + /// Toggles the state of a module based on its enabled property and GPO rules. + /// + /// The module to toggle public static void ToggleModuleStateBasedOnEnabledProperty(IPowerToysModule module) { try @@ -194,6 +215,9 @@ namespace RunnerV2 } } + /// + /// Initializes the tray window to receive system messages. + /// [STAThread] private static void InitializeTrayWindow() { @@ -238,6 +262,9 @@ namespace RunnerV2 } } + /// + /// Handles Windows messages sent to the tray window. + /// private static IntPtr HandleMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) { switch (msg)