PowerToys/src/modules/launcher/PowerLauncher/App.xaml.cs

285 lines
9.9 KiB
C#
Raw Normal View History

2020-08-18 01:00:56 +08:00
// 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.Text;
using System.Threading;
2020-08-18 01:00:56 +08:00
using System.Windows;
using interop;
2020-08-18 01:00:56 +08:00
using ManagedCommon;
using Microsoft.PowerLauncher.Telemetry;
using Microsoft.PowerToys.Common.UI;
2020-08-18 01:00:56 +08:00
using Microsoft.PowerToys.Telemetry;
using PowerLauncher.Helper;
2020-11-04 04:45:01 +08:00
using PowerLauncher.Plugin;
2020-08-18 01:00:56 +08:00
using PowerLauncher.ViewModel;
using Wox;
using Wox.Infrastructure;
using Wox.Infrastructure.Http;
using Wox.Infrastructure.Image;
using Wox.Infrastructure.UserSettings;
using Wox.Plugin;
using Wox.Plugin.Logger;
2020-08-18 01:00:56 +08:00
using Stopwatch = Wox.Infrastructure.Stopwatch;
namespace PowerLauncher
{
public partial class App : IDisposable, ISingleInstanceApp
{
public static PublicAPIInstance API { get; private set; }
2020-08-22 03:40:31 +08:00
private static bool _disposed;
[fxcop] Wox.Infrastructure (#7590) * CA1052: Static holder types should be Static or NotInheritable * CA1041: Provide ObsoleteAttribute message * CA1062: Validate arguments of public methods * CA1304: Specify CultureInfo / CA1305: Specify IFormatProvider / CA1307: Specify StringComparison for clarity * CA1802: Use Literals Where Appropriate * CA1820: Test for empty strings using string length * CA1707: Identifiers should not contain underscores * CA1805: Do not initialize unnecessarily. * CA1822: Mark members as static * CA2227: Collection properties should be read only * CA1054: URI parameters should not be strings * CA1031: Do not catch general exception types * CA1060: Move P/Invokes to NativeMethods class * CA1308: Normalize strings to uppercase * CA2000: Dispose objects before losing scope / CA2234: Pass System.Uri objects instead of strings * CA2234: Pass System.Uri objects instead of strings * CA1044: Properties should not be write only * CA1716: Identifiers should not match keywords * CA2007: Do not directly await a Task * CA2007: Do not directly await a Task (Suppressed) * CA5350: Do Not Use Weak Cryptographic Algorithms (Suppressed) * CA1724: Type names should not match namespaces (renamed Settings.cs to PowerToysRunSettings.cs) * CA1033: Interface methods should be callable by child types (Added sealed modifier to class) * CA1724: Type names should not match namespaces (Renamed Plugin.cs to RunPlugin.cs) * CA1724: Type names should not match namespaces (Renamed Http.cs to HttpClient.cs) * CA5364: Do not use deprecated security protocols (Remove unused code) * Enabled FxCopAnalyzer for Wox.Infrastructure * fixed comment * Addressed comments - Changed Ordinal to InvariantCulture - Added comments - Removed unused obsolete code - Removed unused method (CA2007: Do not directly await a Task) * Addressed comments - fixed justification for CA1031 suppression * Addressed comments - Fixed justification for CA1031 suppression in Wox.Core/Wox.Plugin
2020-10-30 08:52:35 +08:00
private PowerToysRunSettings _settings;
2020-08-18 01:00:56 +08:00
private MainViewModel _mainVM;
private MainWindow _mainWindow;
private ThemeManager _themeManager;
private SettingWindowViewModel _settingsVM;
private StringMatcher _stringMatcher;
private SettingsReader _settingsReader;
2020-08-18 01:00:56 +08:00
[STAThread]
public static void Main()
2020-08-18 01:00:56 +08:00
{
Log.Info($"Starting PowerToys Run with PID={Environment.ProcessId}", typeof(App));
int powerToysPid = GetPowerToysPId();
if (powerToysPid != 0)
2020-08-18 01:00:56 +08:00
{
// The process started from the PT Run module interface. One instance is handled there.
Log.Info($"Runner pid={powerToysPid}", typeof(App));
SingleInstance<App>.CreateInstanceMutex();
}
else
{
// If PT Run is started as standalone application check if there is already running instance
if (!SingleInstance<App>.InitializeAsFirstInstance())
{
Log.Warn("There is already running PowerToys Run instance. Exiting PowerToys Run", typeof(App));
return;
}
}
using (var application = new App())
{
application.InitializeComponent();
new Thread(() =>
2020-08-18 01:00:56 +08:00
{
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.RunExitEvent());
if (eventHandle.WaitOne())
{
Log.Warn("RunExitEvent was signaled. Exiting PowerToys", typeof(App));
ExitPowerToys(application);
}
}).Start();
if (powerToysPid != 0)
{
RunnerHelper.WaitForPowerToysRunner(powerToysPid, () =>
{
Log.Info($"Runner with pid={powerToysPid} exited. Exiting PowerToys Run", typeof(App));
ExitPowerToys(application);
});
2020-08-18 01:00:56 +08:00
}
application.Run();
2021-05-21 22:24:33 +08:00
}
2020-08-18 01:00:56 +08:00
}
private void OnStartup(object sender, StartupEventArgs e)
{
2021-05-21 22:24:33 +08:00
Log.Info("On Startup.", GetType());
2020-08-18 01:00:56 +08:00
var bootTime = new System.Diagnostics.Stopwatch();
bootTime.Start();
Stopwatch.Normal("App.OnStartup - Startup cost", () =>
2020-08-18 01:00:56 +08:00
{
var textToLog = new StringBuilder();
textToLog.AppendLine("Begin PowerToys Run startup ----------------------------------------------------");
textToLog.AppendLine($"Runtime info:{ErrorReporting.RuntimeInfo()}");
2020-08-18 01:00:56 +08:00
RegisterAppDomainExceptions();
RegisterDispatcherUnhandledException();
_themeManager = new ThemeManager(this);
ImageLoader.Initialize(_themeManager.GetCurrentTheme());
_settingsVM = new SettingWindowViewModel();
_settings = _settingsVM.Settings;
_settings.UsePowerToysRunnerKeyboardHook = e.Args.Contains("--centralized-kb-hook");
2020-08-18 01:00:56 +08:00
_stringMatcher = new StringMatcher();
2020-08-18 01:00:56 +08:00
StringMatcher.Instance = _stringMatcher;
_stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
_mainVM = new MainViewModel(_settings);
_mainWindow = new MainWindow(_settings, _mainVM);
API = new PublicAPIInstance(_settingsVM, _mainVM, _themeManager);
_settingsReader = new SettingsReader(_settings, _themeManager);
_settingsReader.ReadSettings();
2020-08-18 01:00:56 +08:00
PluginManager.InitializePlugins(API);
Current.MainWindow = _mainWindow;
Current.MainWindow.Title = Constant.ExeFileName;
// main windows needs initialized before theme change because of blur settings
[fxcop] Wox.Infrastructure (#7590) * CA1052: Static holder types should be Static or NotInheritable * CA1041: Provide ObsoleteAttribute message * CA1062: Validate arguments of public methods * CA1304: Specify CultureInfo / CA1305: Specify IFormatProvider / CA1307: Specify StringComparison for clarity * CA1802: Use Literals Where Appropriate * CA1820: Test for empty strings using string length * CA1707: Identifiers should not contain underscores * CA1805: Do not initialize unnecessarily. * CA1822: Mark members as static * CA2227: Collection properties should be read only * CA1054: URI parameters should not be strings * CA1031: Do not catch general exception types * CA1060: Move P/Invokes to NativeMethods class * CA1308: Normalize strings to uppercase * CA2000: Dispose objects before losing scope / CA2234: Pass System.Uri objects instead of strings * CA2234: Pass System.Uri objects instead of strings * CA1044: Properties should not be write only * CA1716: Identifiers should not match keywords * CA2007: Do not directly await a Task * CA2007: Do not directly await a Task (Suppressed) * CA5350: Do Not Use Weak Cryptographic Algorithms (Suppressed) * CA1724: Type names should not match namespaces (renamed Settings.cs to PowerToysRunSettings.cs) * CA1033: Interface methods should be callable by child types (Added sealed modifier to class) * CA1724: Type names should not match namespaces (Renamed Plugin.cs to RunPlugin.cs) * CA1724: Type names should not match namespaces (Renamed Http.cs to HttpClient.cs) * CA5364: Do not use deprecated security protocols (Remove unused code) * Enabled FxCopAnalyzer for Wox.Infrastructure * fixed comment * Addressed comments - Changed Ordinal to InvariantCulture - Added comments - Removed unused obsolete code - Removed unused method (CA2007: Do not directly await a Task) * Addressed comments - fixed justification for CA1031 suppression * Addressed comments - Fixed justification for CA1031 suppression in Wox.Core/Wox.Plugin
2020-10-30 08:52:35 +08:00
HttpClient.Proxy = _settings.Proxy;
2020-08-18 01:00:56 +08:00
RegisterExitEvents();
_settingsReader.ReadSettingsOnChange();
2020-08-18 01:00:56 +08:00
_mainVM.MainWindowVisibility = Visibility.Visible;
_mainVM.ColdStartFix();
_themeManager.ThemeChanged += OnThemeChanged;
textToLog.AppendLine("End PowerToys Run startup ---------------------------------------------------- ");
2020-08-18 01:00:56 +08:00
bootTime.Stop();
Log.Info(textToLog.ToString(), GetType());
_mainVM.RegisterHotkey();
2020-08-18 01:00:56 +08:00
PowerToysTelemetry.Log.WriteEvent(new LauncherBootEvent() { BootTimeMs = bootTime.ElapsedMilliseconds });
// [Conditional("RELEASE")]
// check update every 5 hours
// check updates on startup
});
}
private static void ExitPowerToys(App app)
{
SingleInstance<App>.SingleInstanceMutex.Close();
try
{
app.Dispose();
}
finally
{
Environment.Exit(0);
}
}
private static int GetPowerToysPId()
{
var args = Environment.GetCommandLineArgs();
for (int i = 0; i + 1 < args.Length; i++)
{
if (args[i] == "-powerToysPid")
{
int powerToysPid;
if (int.TryParse(args[i + 1], out powerToysPid))
{
return powerToysPid;
}
break;
}
}
return 0;
}
2020-08-18 01:00:56 +08:00
private void RegisterExitEvents()
{
AppDomain.CurrentDomain.ProcessExit += (s, e) =>
{
Log.Info("AppDomain.CurrentDomain.ProcessExit", GetType());
Dispose();
};
Current.Exit += (s, e) =>
{
Log.Info("Application.Current.Exit", GetType());
Dispose();
};
Current.SessionEnding += (s, e) =>
{
Log.Info("Application.Current.SessionEnding", GetType());
Dispose();
};
2020-08-18 01:00:56 +08:00
}
/// <summary>
/// Callback when windows theme is changed.
/// </summary>
/// <param name="oldTheme">Previous Theme</param>
/// <param name="newTheme">Current Theme</param>
private void OnThemeChanged(Theme oldTheme, Theme newTheme)
{
ImageLoader.UpdateIconPath(newTheme);
_mainVM.Query();
}
/// <summary>
/// let exception throw as normal is better for Debug
/// </summary>
[Conditional("RELEASE")]
private void RegisterDispatcherUnhandledException()
{
DispatcherUnhandledException += ErrorReporting.DispatcherUnhandledException;
}
/// <summary>
/// let exception throw as normal is better for Debug
/// </summary>
[Conditional("RELEASE")]
private static void RegisterAppDomainExceptions()
{
AppDomain.CurrentDomain.UnhandledException += ErrorReporting.UnhandledExceptionHandle;
}
public void OnSecondAppStarted()
{
Current.MainWindow.Visibility = Visibility.Visible;
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
Stopwatch.Normal("App.OnExit - Exit cost", () =>
2020-08-18 01:00:56 +08:00
{
Log.Info("Start PowerToys Run Exit---------------------------------------------------- ", GetType());
2020-08-18 01:00:56 +08:00
if (disposing)
{
if (_themeManager != null)
{
_themeManager.ThemeChanged -= OnThemeChanged;
}
API?.SaveAppAllSettings();
2020-08-18 01:00:56 +08:00
PluginManager.Dispose();
_mainWindow?.Dispose();
API?.Dispose();
_mainVM?.Dispose();
_themeManager?.Dispose();
2020-08-18 01:00:56 +08:00
_disposed = true;
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null
_disposed = true;
Log.Info("End PowerToys Run Exit ---------------------------------------------------- ", GetType());
2020-08-18 01:00:56 +08:00
});
}
}
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
// ~App()
// {
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
// Dispose(disposing: false);
// }
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}