mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-12-24 00:48:00 +08:00
db191b8b75
* Imported offline solution * Make solution compile * Add Windows sample, doesn't work? * Added new project to implement the dll * Remove unneeded header * Implemented IUnknown part of ExplorerCommand * Implemented IExplorerCommand methods * Implemented ClassFactory * Implemented DLL register/unregister * Implemented other DLL exports, not working? * Implemented IShellExtInit inferface * Implemented IContextMenu, it works! * Implement command data fetching * Make sample project compile on VS 2022 * Add plan * Implement Lib as separate project * Implemented IPC, not tested * Console UI project skeleton * Implemented basic console UI * Implemented piping, there are bugs * Prototype works * Remove old project * Added GUI project skeleton * Mitigate issue with WinUI3 * Added a control for displaying results * Add button * Implement core functions in lib project * Call new library function from console main * Implement showing results * Improve UI * Implemented subdirectory search * Remove useless code * Set window size * UI adjustments * Implement killing process * Rename variable * Add lib project to main solution * Add Ext and GUI projects to solution * Tweak packages for GUI project * Add a settings page * Add a few resource strings * Add one more resources string * VS keeps trying to correct this * Add references to File Locksmith in /,github * Implement some parts of FileLocksmithModule * Change output directory * Change target name and add to runner * Add logger * Started implementing settings backend * Fix log folder * Settings work * Add some basic tracing * Attempt at adding resources * Remove junk files * Added missing defines * Replaced some constants with resources Something's not working * Move resources to the Ext project * Remove experiment * Add binaries for signing * Improve tracing * Remove old Settings calls * Show something when there are no results * Change window title * Move computation to another thread, improve UX * Increase font size for default text * Remove entries for killed processes * Show user name * Remove nonrecursive implementation * Implement back end for getting file names * Show list of files, UI tweaks * Remove useless includes * Implement back end for getting full process path * Dark title bar on dark themes * Using Expander, other UI adjustments * Show "No results" after killing all processes * Show progress ring * Update configuration mapping * Revert "Update configuration mapping" This reverts commit d8e13206f3c7de3c6dbf880299bfff3bf9f27a37. * Fixed solution configuration, ARM64 should build * Backend for refreshing * Variable window size * Add refresh button * New WinUI3 C# project for FL * Started porting functionality * Add Interop project * Move IPC to Ext project * Ported native functions to Interop * Ported finding processes * Ported most of Main Window functionality * Display paths of files * Implement killing processes * Use resource string for "End Task" * Remove entries for terminated processes * Show User name * Set default window size * Make the new UI the default * Reading paths from stdin, completed port to C# * Fix small bug * Moving to MVVM * Adding Labs * Merge branch 'ivan/file-locksmith' of https://github.com/microsoft/PowerToys into ivan/file-locksmith Removing one parent commit for cleaner history Co-Authored-By: Niels Laute <niels.laute@live.nl> * Reintroducing features * Moving UI strings to resources file * Restored functionality * Add missing dlls * Add FIle Locksmith to publish.cmd * Rebase fixes * Try updating nuget.config * Fix copy-paste blunder * Add File Locksmith UI for publishing * Add .pubxml file in FileLocksmith * Change build output folder * Fix installer build issues Remove old projects from solution so MSBuild doesn't build them. Downgrade target framework to what most other projects are using. Fix publishing profile and project runtimes. Remove unused CsWinRT references. * [CI] Add clear to nuget packages * Fix module reference counting * Fix nuget for release CI * Fix version and signing * Fix path for resources * Fix incorrect results when running 2 instances * Fix default nuget source * Windows 10 icon and fallback for UI * Code clean-up and spaces instead of tabs * Add gif showcasing FL * Add screenshot of File Locksmith for Settings * Add new files to the installer * Add OOBE page * Showing selected paths in the header * Tweak path list * Added new, wider gif * Add GPO * Add some logs * [CI]Get CommunityToolkit.Labs from BigPark feed * [CI]Use azure package feed for Nuget in release * [CI]Another try for the labs source * Revert changes to feed * Use RestoreAdditionalProjectSources * Add tooltip to file list * Change tooltip to not trim the lines * Add Tips and tricks section mentioning elevated * Add some more logs messages. * Grammar fix * Add to bug report tool * Fix UI virtualization not working * Disable virtualization to avoid crashes * Get better virtualization * Add dialog instead of tooltip to show list of items * No results refresh icon is now a button too * Use managed methods for handling processes * Remove registry code from Ext. * Support drives too Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com>
308 lines
12 KiB
C#
308 lines
12 KiB
C#
// 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.Linq;
|
|
using System.Threading.Tasks;
|
|
using interop;
|
|
using ManagedCommon;
|
|
using Microsoft.PowerToys.Settings.UI.Helpers;
|
|
using Microsoft.PowerToys.Settings.UI.Library;
|
|
using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
|
|
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
|
using Microsoft.PowerToys.Telemetry;
|
|
using Microsoft.UI.Xaml;
|
|
using Windows.UI.Popups;
|
|
using WinRT.Interop;
|
|
|
|
namespace Microsoft.PowerToys.Settings.UI
|
|
{
|
|
/// <summary>
|
|
/// Provides application-specific behavior to supplement the default Application class.
|
|
/// </summary>
|
|
public partial class App : Application
|
|
{
|
|
private enum Arguments
|
|
{
|
|
PTPipeName = 1,
|
|
SettingsPipeName,
|
|
PTPid,
|
|
Theme, // used in the old settings
|
|
ElevatedStatus,
|
|
IsUserAdmin,
|
|
ShowOobeWindow,
|
|
ShowScoobeWindow,
|
|
SettingsWindow,
|
|
}
|
|
|
|
// Quantity of arguments
|
|
private const int RequiredArgumentsQty = 9;
|
|
private const int RequiredAndOptionalArgumentsQty = 10;
|
|
|
|
// Create an instance of the IPC wrapper.
|
|
private static TwoWayPipeMessageIPCManaged ipcmanager;
|
|
|
|
public static bool IsElevated { get; set; }
|
|
|
|
public static bool IsUserAnAdmin { get; set; }
|
|
|
|
public static int PowerToysPID { get; set; }
|
|
|
|
public bool ShowOobe { get; set; }
|
|
|
|
public bool ShowScoobe { get; set; }
|
|
|
|
public Type StartupPage { get; set; } = typeof(Views.GeneralPage);
|
|
|
|
public static Action<string> IPCMessageReceivedCallback { get; set; }
|
|
|
|
private static bool loggedImmersiveDarkException;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="App"/> class.
|
|
/// Initializes the singleton application object. This is the first line of authored code
|
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
|
/// </summary>
|
|
public App()
|
|
{
|
|
this.InitializeComponent();
|
|
}
|
|
|
|
public static void OpenSettingsWindow(Type type)
|
|
{
|
|
if (settingsWindow == null)
|
|
{
|
|
settingsWindow = new MainWindow(IsDarkTheme());
|
|
}
|
|
|
|
settingsWindow.Activate();
|
|
settingsWindow.NavigateToSection(type);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invoked when the application is launched normally by the end user. Other entry points
|
|
/// will be used such as when the application is launched to open a specific file.
|
|
/// </summary>
|
|
/// <param name="args">Details about the launch request and process.</param>
|
|
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
|
|
{
|
|
var cmdArgs = Environment.GetCommandLineArgs();
|
|
var isDark = IsDarkTheme();
|
|
|
|
if (cmdArgs != null && cmdArgs.Length >= RequiredArgumentsQty)
|
|
{
|
|
// Skip the first argument which is prepended when launched by explorer
|
|
if (cmdArgs[0].EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) && cmdArgs[1].EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase) && (cmdArgs.Length >= RequiredArgumentsQty + 1))
|
|
{
|
|
cmdArgs = cmdArgs.Skip(1).ToArray();
|
|
}
|
|
|
|
_ = int.TryParse(cmdArgs[(int)Arguments.PTPid], out int powerToysPID);
|
|
PowerToysPID = powerToysPID;
|
|
|
|
IsElevated = cmdArgs[(int)Arguments.ElevatedStatus] == "true";
|
|
IsUserAnAdmin = cmdArgs[(int)Arguments.IsUserAdmin] == "true";
|
|
ShowOobe = cmdArgs[(int)Arguments.ShowOobeWindow] == "true";
|
|
ShowScoobe = cmdArgs[(int)Arguments.ShowScoobeWindow] == "true";
|
|
|
|
if (cmdArgs.Length == RequiredAndOptionalArgumentsQty)
|
|
{
|
|
// open specific window
|
|
switch (cmdArgs[(int)Arguments.SettingsWindow])
|
|
{
|
|
case "Overview": StartupPage = typeof(Views.GeneralPage); break;
|
|
case "AlwaysOnTop": StartupPage = typeof(Views.AlwaysOnTopPage); break;
|
|
case "Awake": StartupPage = typeof(Views.AwakePage); break;
|
|
case "ColorPicker": StartupPage = typeof(Views.ColorPickerPage); break;
|
|
case "FancyZones": StartupPage = typeof(Views.FancyZonesPage); break;
|
|
case "FileLocksmith": StartupPage = typeof(Views.FileLocksmithPage); break;
|
|
case "Run": StartupPage = typeof(Views.PowerLauncherPage); break;
|
|
case "ImageResizer": StartupPage = typeof(Views.ImageResizerPage); break;
|
|
case "KBM": StartupPage = typeof(Views.KeyboardManagerPage); break;
|
|
case "MouseUtils": StartupPage = typeof(Views.MouseUtilsPage); break;
|
|
case "PowerRename": StartupPage = typeof(Views.PowerRenamePage); break;
|
|
case "QuickAccent": StartupPage = typeof(Views.PowerAccentPage); break;
|
|
case "FileExplorer": StartupPage = typeof(Views.PowerPreviewPage); break;
|
|
case "ShortcutGuide": StartupPage = typeof(Views.ShortcutGuidePage); break;
|
|
case "TextExtractor": StartupPage = typeof(Views.PowerOcrPage); break;
|
|
case "VideoConference": StartupPage = typeof(Views.VideoConferencePage); break;
|
|
case "MeasureTool": StartupPage = typeof(Views.MeasureToolPage); break;
|
|
case "Hosts": StartupPage = typeof(Views.HostsPage); break;
|
|
default: Debug.Assert(false, "Unexpected SettingsWindow argument value"); break;
|
|
}
|
|
}
|
|
|
|
RunnerHelper.WaitForPowerToysRunner(PowerToysPID, () =>
|
|
{
|
|
Environment.Exit(0);
|
|
});
|
|
|
|
ipcmanager = new TwoWayPipeMessageIPCManaged(cmdArgs[(int)Arguments.SettingsPipeName], cmdArgs[(int)Arguments.PTPipeName], (string message) =>
|
|
{
|
|
if (IPCMessageReceivedCallback != null && message.Length > 0)
|
|
{
|
|
IPCMessageReceivedCallback(message);
|
|
}
|
|
});
|
|
ipcmanager.Start();
|
|
|
|
if (!ShowOobe && !ShowScoobe)
|
|
{
|
|
settingsWindow = new MainWindow(isDark);
|
|
settingsWindow.Activate();
|
|
settingsWindow.NavigateToSection(StartupPage);
|
|
}
|
|
else
|
|
{
|
|
// Create the Settings window hidden so that it's fully initialized and
|
|
// it will be ready to receive the notification if the user opens
|
|
// the Settings from the tray icon.
|
|
settingsWindow = new MainWindow(isDark, true);
|
|
|
|
if (ShowOobe)
|
|
{
|
|
PowerToysTelemetry.Log.WriteEvent(new OobeStartedEvent());
|
|
OobeWindow oobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.Overview, isDark);
|
|
oobeWindow.Activate();
|
|
SetOobeWindow(oobeWindow);
|
|
}
|
|
else if (ShowScoobe)
|
|
{
|
|
PowerToysTelemetry.Log.WriteEvent(new ScoobeStartedEvent());
|
|
OobeWindow scoobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.WhatsNew, isDark);
|
|
scoobeWindow.Activate();
|
|
SetOobeWindow(scoobeWindow);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// For debugging purposes
|
|
// Window is also needed to show MessageDialog
|
|
settingsWindow = new MainWindow(isDark);
|
|
settingsWindow.Activate();
|
|
|
|
#if !DEBUG
|
|
ShowMessageDialogAndExit("The application cannot be run as a standalone process. Please start the application through the runner.", "Forbidden");
|
|
#else
|
|
ShowMessageDialog("The application cannot be run as a standalone process. Please start the application through the runner.", "Forbidden");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if !DEBUG
|
|
private async void ShowMessageDialogAndExit(string content, string title = null)
|
|
#else
|
|
private async void ShowMessageDialog(string content, string title = null)
|
|
#endif
|
|
{
|
|
await ShowDialogAsync(content, title);
|
|
#if !DEBUG
|
|
this.Exit();
|
|
#endif
|
|
}
|
|
|
|
public static Task<IUICommand> ShowDialogAsync(string content, string title = null)
|
|
{
|
|
var dialog = new MessageDialog(content, title ?? string.Empty);
|
|
var handle = NativeMethods.GetActiveWindow();
|
|
if (handle == IntPtr.Zero)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
InitializeWithWindow.Initialize(dialog, handle);
|
|
return dialog.ShowAsync().AsTask<IUICommand>();
|
|
}
|
|
|
|
public static TwoWayPipeMessageIPCManaged GetTwoWayIPCManager()
|
|
{
|
|
return ipcmanager;
|
|
}
|
|
|
|
public static string SelectedTheme()
|
|
{
|
|
return SettingsRepository<GeneralSettings>.GetInstance(settingsUtils).SettingsConfig.Theme.ToUpper(CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
public static bool IsDarkTheme()
|
|
{
|
|
var selectedTheme = SelectedTheme();
|
|
return selectedTheme == "DARK" || (selectedTheme == "SYSTEM" && ThemeHelpers.GetAppTheme() == AppTheme.Dark);
|
|
}
|
|
|
|
public static void HandleThemeChange()
|
|
{
|
|
try
|
|
{
|
|
var isDark = IsDarkTheme();
|
|
if (settingsWindow != null)
|
|
{
|
|
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(settingsWindow);
|
|
ThemeHelpers.SetImmersiveDarkMode(hWnd, isDark);
|
|
}
|
|
|
|
if (oobeWindow != null)
|
|
{
|
|
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(oobeWindow);
|
|
ThemeHelpers.SetImmersiveDarkMode(hWnd, isDark);
|
|
}
|
|
|
|
var selectedTheme = SelectedTheme();
|
|
if (selectedTheme == "SYSTEM")
|
|
{
|
|
themeListener = new ThemeListener();
|
|
themeListener.ThemeChanged += (_) => HandleThemeChange();
|
|
}
|
|
else if (themeListener != null)
|
|
{
|
|
themeListener.Dispose();
|
|
themeListener = null;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
if (!loggedImmersiveDarkException)
|
|
{
|
|
Logger.LogError($"HandleThemeChange exception. Please install .NET 4.", e);
|
|
loggedImmersiveDarkException = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static ISettingsUtils settingsUtils = new SettingsUtils();
|
|
|
|
private static MainWindow settingsWindow;
|
|
private static OobeWindow oobeWindow;
|
|
private static ThemeListener themeListener;
|
|
|
|
public static void ClearSettingsWindow()
|
|
{
|
|
settingsWindow = null;
|
|
}
|
|
|
|
public static MainWindow GetSettingsWindow()
|
|
{
|
|
return settingsWindow;
|
|
}
|
|
|
|
public static OobeWindow GetOobeWindow()
|
|
{
|
|
return oobeWindow;
|
|
}
|
|
|
|
public static void SetOobeWindow(OobeWindow window)
|
|
{
|
|
oobeWindow = window;
|
|
}
|
|
|
|
public static void ClearOobeWindow()
|
|
{
|
|
oobeWindow = null;
|
|
}
|
|
}
|
|
}
|