Add some documentation

This commit is contained in:
Noraa Junker
2025-12-11 18:15:07 +01:00
parent 123d318d6a
commit 5398c16456
7 changed files with 99 additions and 31 deletions

View File

@@ -72,7 +72,13 @@ namespace RunnerV2.Helpers
return [.. matchedFiles]; return [.. matchedFiles];
} }
internal static bool RegisterPackage(string packagePath, string[] dependencies) /// <summary>
/// Installs the specified appx package along with its dependencies.
/// </summary>
/// <param name="packagePath">Path to the package</param>
/// <param name="dependencies">Array of dependency package paths</param>
/// <returns>True if the installation was successful, false otherwise</returns>
internal static bool InstallPackage(string packagePath, string[] dependencies)
{ {
Logger.LogInfo("Starting package install of package \"" + packagePath + "\""); Logger.LogInfo("Starting package install of package \"" + packagePath + "\"");
PackageManager packageManager = new(); PackageManager packageManager = new();
@@ -129,6 +135,11 @@ namespace RunnerV2.Helpers
return false; return false;
} }
/// <summary>
/// Checks if the package specified by the given path is already installed and satisfies the required version.
/// </summary>
/// <param name="packagePath">Path to the package.</param>
/// <returns>True if the package is already installed and satisfies the required version, false otherwise.</returns>
private static bool IsPackageSatisfied(string packagePath) private static bool IsPackageSatisfied(string packagePath)
{ {
if (!GetPackageNameAndVersionFromAppx(packagePath, out string name, out PackageVersion version)) if (!GetPackageNameAndVersionFromAppx(packagePath, out string name, out PackageVersion version))
@@ -153,6 +164,13 @@ namespace RunnerV2.Helpers
return false; return false;
} }
/// <summary>
/// Gets the package name and version from the specified appx package file.
/// </summary>
/// <param name="packagePath">Path to the package file.</param>
/// <param name="name">Output parameter for the package name.</param>
/// <param name="packageVersion">Output parameter for the package version.</param>
/// <returns>True if the package name and version were successfully retrieved, false otherwise.</returns>
private static bool GetPackageNameAndVersionFromAppx(string packagePath, out string name, out PackageVersion packageVersion) private static bool GetPackageNameAndVersionFromAppx(string packagePath, out string name, out PackageVersion packageVersion)
{ {
// Todo: Implement this without interop if possible // Todo: Implement this without interop if possible

View File

@@ -10,16 +10,17 @@ using System.IO;
using System.IO.Pipelines; using System.IO.Pipelines;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Threading;
using ManagedCommon; using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library; using Microsoft.PowerToys.Settings.UI.Library;
using PowerToys.Interop; using PowerToys.Interop;
using RunnerV2.ModuleInterfaces; using RunnerV2.ModuleInterfaces;
using Update; using Update;
using Windows.Media.Devices;
namespace RunnerV2.Helpers namespace RunnerV2.Helpers
{ {
/// <summary>
/// This class provides helper methods to interact with the PowerToys Settings window.
/// </summary>
internal static class SettingsHelper internal static class SettingsHelper
{ {
private static readonly SettingsUtils _settingsUtils = new(); private static readonly SettingsUtils _settingsUtils = new();

View File

@@ -59,7 +59,7 @@ namespace RunnerV2.ModuleInterfaces
if (msixFiles.Length > 0) if (msixFiles.Length > 0)
{ {
if (!PackageHelper.RegisterPackage(msixFiles[0], dependencies)) if (!PackageHelper.InstallPackage(msixFiles[0], dependencies))
{ {
Logger.LogError("Failed to register Command Palette package."); Logger.LogError("Failed to register Command Palette package.");
} }

View File

@@ -15,6 +15,9 @@ using RunnerV2.Helpers;
namespace RunnerV2.ModuleInterfaces namespace RunnerV2.ModuleInterfaces
{ {
/// <summary>
/// Base abstract class for modules that launch and manage external processes.
/// </summary>
internal abstract class ProcessModuleAbstractClass internal abstract class ProcessModuleAbstractClass
{ {
/// <summary> /// <summary>
@@ -55,14 +58,36 @@ namespace RunnerV2.ModuleInterfaces
NeverExit = 32, NeverExit = 32,
} }
/// <summary>
/// Gets the relative or absolute path to the process executable.
/// </summary>
public abstract string ProcessPath { get; } public abstract string ProcessPath { get; }
/// <summary>
/// Gets the name of the process without the .exe extension.
/// </summary>
/// <remarks>
/// Has no effect if the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.UseShellExecute"/> flag set.
/// </remarks>
public abstract string ProcessName { get; } public abstract string ProcessName { get; }
/// <summary>
/// Gets the arguments to pass to the process on launch.
/// </summary>
/// <remarks>
/// If not overridden, no arguments are passed.
/// If the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.RunnerProcessIdAsFirstArgument"/> flag is set, the runner process ID is prepended to these arguments.
/// </remarks>
public virtual string ProcessArguments { get; } = string.Empty; public virtual string ProcessArguments { get; } = string.Empty;
/// <summary>
/// Gets the options used to configure how the process is launched.
/// </summary>
public abstract ProcessLaunchOptions LaunchOptions { get; } public abstract ProcessLaunchOptions LaunchOptions { get; }
/// <summary>
/// Ensures that atleast one process is launched. If the process is already running, does nothing.
/// </summary>
public void EnsureLaunched() public void EnsureLaunched()
{ {
Process[] processes = Process.GetProcessesByName(ProcessName); Process[] processes = Process.GetProcessesByName(ProcessName);
@@ -74,6 +99,10 @@ namespace RunnerV2.ModuleInterfaces
LaunchProcess(); LaunchProcess();
} }
/// <summary>
/// Launches the process with the specified options.
/// </summary>
/// <param name="isModuleEnableProcess">Specifies if the <see cref="Runner"/> class is currently calling this function as part of a module startup</param>
public void LaunchProcess(bool isModuleEnableProcess = false) public void LaunchProcess(bool isModuleEnableProcess = false)
{ {
if (isModuleEnableProcess && LaunchOptions.HasFlag(ProcessLaunchOptions.SupressLaunchOnModuleEnabled)) if (isModuleEnableProcess && LaunchOptions.HasFlag(ProcessLaunchOptions.SupressLaunchOnModuleEnabled))
@@ -101,14 +130,20 @@ namespace RunnerV2.ModuleInterfaces
}); });
} }
public void ProcessExit(int msDelay = 500) /// <summary>
/// Schedules all processes with the specified <see cref="ProcessName"/>.
/// </summary>
/// <remarks>
/// If the <see cref="LaunchOptions"/> has the <see cref="ProcessLaunchOptions.NeverExit"/> flag set, this function does nothing.
/// </remarks>
public void ProcessExit()
{ {
if (LaunchOptions.HasFlag(ProcessLaunchOptions.NeverExit)) if (LaunchOptions.HasFlag(ProcessLaunchOptions.NeverExit))
{ {
return; return;
} }
ProcessHelper.ScheudleProcessKill(ProcessName, msDelay); ProcessHelper.ScheudleProcessKill(ProcessName);
} }
} }
} }

View File

@@ -190,11 +190,6 @@ namespace RunnerV2
public string LpszClassName; 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")] [DllImport("Advapi32.dll")]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool ConvertStringSecurityDescriptorToSecurityDescriptorW( internal static extern bool ConvertStringSecurityDescriptorToSecurityDescriptorW(
@@ -233,22 +228,6 @@ namespace RunnerV2
[DllImport("user32.dll")] [DllImport("user32.dll")]
internal static extern uint SendInput(uint nInputs, NativeKeyboardHelper.INPUT[] pInputs, int cbSize); 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)] [DllImport("PowerToys.Interop.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool GetPackageNameAndVersionFromAppx( internal static extern bool GetPackageNameAndVersionFromAppx(
[MarshalAs(UnmanagedType.LPWStr)] string appxPath, [MarshalAs(UnmanagedType.LPWStr)] string appxPath,

View File

@@ -111,7 +111,7 @@ internal sealed class Program
tempGeneralSettings.IsElevated = isElevated; tempGeneralSettings.IsElevated = isElevated;
_settingsUtils.SaveSettings(tempGeneralSettings.ToJsonString()); _settingsUtils.SaveSettings(tempGeneralSettings.ToJsonString());
_ = Runner.Run(afterInitializationAction); Runner.Run(afterInitializationAction);
break; break;
default: default:
ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevated; ElevationHelper.RestartScheduled = ElevationHelper.RestartScheduledMode.RestartElevated;
@@ -121,6 +121,11 @@ internal sealed class Program
ElevationHelper.RestartIfScheudled(); ElevationHelper.RestartIfScheudled();
} }
/// <summary>
/// Returns whether the application should run in a special mode based on the provided arguments.
/// </summary>
/// <param name="args">The arguments passed to <see cref="Main(string[])"/></param>
/// <returns>The <see cref="SpecialMode"/> the app should run in.</returns>
private static SpecialMode ShouldRunInSpecialMode(string[] args) private static SpecialMode ShouldRunInSpecialMode(string[] args)
{ {
if (args.Length > 0 && args[0].StartsWith("powertoys://", StringComparison.InvariantCultureIgnoreCase)) if (args.Length > 0 && args[0].StartsWith("powertoys://", StringComparison.InvariantCultureIgnoreCase))
@@ -137,6 +142,9 @@ internal sealed class Program
return SpecialMode.None; return SpecialMode.None;
} }
/// <summary>
/// Starts the update process for PowerToys.
/// </summary>
private static void UpdateNow() private static void UpdateNow()
{ {
Process.Start(new ProcessStartInfo() Process.Start(new ProcessStartInfo()

View File

@@ -27,12 +27,21 @@ namespace RunnerV2
{ {
internal static partial class Runner internal static partial class Runner
{ {
/// <summary>
/// Gets the window handle for the Runner main window that hosts the tray icon and receives system messages.
/// </summary>
public static nint RunnerHwnd { get; private set; } public static nint RunnerHwnd { get; private set; }
private const string TrayWindowClassName = "pt_tray_icon_window_class"; private const string TrayWindowClassName = "pt_tray_icon_window_class";
/// <summary>
/// Gets all the currently loaded modules.
/// </summary>
public static List<IPowerToysModule> LoadedModules { get; } = []; public static List<IPowerToysModule> LoadedModules { get; } = [];
/// <summary>
/// Gets the list of all available PowerToys modules.
/// </summary>
public static FrozenSet<IPowerToysModule> ModulesToLoad { get; } = public static FrozenSet<IPowerToysModule> ModulesToLoad { get; } =
[ [
new ColorPickerModuleInterface(), new ColorPickerModuleInterface(),
@@ -46,7 +55,11 @@ namespace RunnerV2
new CropAndLockModuleInterface(), new CropAndLockModuleInterface(),
]; ];
internal static bool Run(Action afterInitializationAction) /// <summary>
/// Runs the main message loop for Runner.
/// </summary>
/// <param name="afterInitializationAction">A function to execute after initialization.</param>
internal static void Run(Action afterInitializationAction)
{ {
Logger.LogInfo("Runner started"); Logger.LogInfo("Runner started");
@@ -65,12 +78,13 @@ namespace RunnerV2
afterInitializationAction(); afterInitializationAction();
MessageLoop(); MessageLoop();
return true;
} }
private static readonly uint _taskbarCreatedMessage = RegisterWindowMessageW("TaskbarCreated"); private static readonly uint _taskbarCreatedMessage = RegisterWindowMessageW("TaskbarCreated");
/// <summary>
/// The main message loop that processes Windows messages.
/// </summary>
[STAThread] [STAThread]
private static void MessageLoop() private static void MessageLoop()
{ {
@@ -91,6 +105,9 @@ namespace RunnerV2
Close(); Close();
} }
/// <summary>
/// Closes Runner and all loaded modules.
/// </summary>
[DoesNotReturn] [DoesNotReturn]
internal static void Close() internal static void Close()
{ {
@@ -123,6 +140,10 @@ namespace RunnerV2
Environment.Exit(0); Environment.Exit(0);
} }
/// <summary>
/// Toggles the state of a module based on its enabled property and GPO rules.
/// </summary>
/// <param name="module">The module to toggle</param>
public static void ToggleModuleStateBasedOnEnabledProperty(IPowerToysModule module) public static void ToggleModuleStateBasedOnEnabledProperty(IPowerToysModule module)
{ {
try try
@@ -194,6 +215,9 @@ namespace RunnerV2
} }
} }
/// <summary>
/// Initializes the tray window to receive system messages.
/// </summary>
[STAThread] [STAThread]
private static void InitializeTrayWindow() private static void InitializeTrayWindow()
{ {
@@ -238,6 +262,9 @@ namespace RunnerV2
} }
} }
/// <summary>
/// Handles Windows messages sent to the tray window.
/// </summary>
private static IntPtr HandleMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) private static IntPtr HandleMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{ {
switch (msg) switch (msg)