From 6fdfd3b9e7c127b406c582a2963427d9e8ceca78 Mon Sep 17 00:00:00 2001 From: Yevhenii Holovachov <55396981+yevhenii44@users.noreply.github.com> Date: Wed, 10 Jun 2020 20:58:34 +0300 Subject: [PATCH] [PT Run] Closing PT Run and new settings app when PowerToys is not running (#3853) Closing PowerLauncher, FZ Editor and new settings app when PowerToys is not running --- src/action_runner/action_runner.cpp | 4 ++- .../Program.cs | 32 +++++++++++++++++++ .../editor/FancyZonesEditor/App.xaml.cs | 27 ++++++++++++++++ .../FancyZonesEditor/Models/Settings.cs | 12 ++++++- src/modules/fancyzones/lib/FancyZones.cpp | 3 +- .../launcher/Microsoft.Launcher/dllmain.cpp | 7 ++++ .../launcher/PowerLauncher/App.xaml.cs | 32 +++++++++++++++++-- 7 files changed, 111 insertions(+), 6 deletions(-) diff --git a/src/action_runner/action_runner.cpp b/src/action_runner/action_runner.cpp index ce3c6bd87f..9977fe72fa 100644 --- a/src/action_runner/action_runner.cpp +++ b/src/action_runner/action_runner.cpp @@ -192,6 +192,7 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) std::wstring_view target; std::wstring_view pidFile; + std::wstring params; while (nextArg < nArgs) { @@ -207,6 +208,7 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) } else { + params = args[nextArg]; nextArg++; } } @@ -227,7 +229,7 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) } } - run_same_elevation(target.data(), L"", pidBuffer); + run_same_elevation(target.data(), params, pidBuffer); // cleanup if (!pidFile.empty()) diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Runner/Program.cs b/src/core/Microsoft.PowerToys.Settings.UI.Runner/Program.cs index accd850759..8449b0eba2 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Runner/Program.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Runner/Program.cs @@ -3,6 +3,9 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading.Tasks; using System.Windows; using interop; using Windows.UI.Popups; @@ -21,6 +24,8 @@ namespace Microsoft.PowerToys.Settings.UI.Runner public static bool IsUserAnAdmin { get; set; } + public static int PowerToysPID { get; set; } + [STAThread] public static void Main(string[] args) { @@ -31,6 +36,9 @@ namespace Microsoft.PowerToys.Settings.UI.Runner if (args.Length >= ArgumentsQty) { + int.TryParse(args[2], out int powerToysPID); + PowerToysPID = powerToysPID; + if (args[4] == "true") { IsElevated = true; @@ -49,6 +57,8 @@ namespace Microsoft.PowerToys.Settings.UI.Runner IsUserAnAdmin = false; } + WaitForPowerToysRunner(); + ipcmanager = new TwoWayPipeMessageIPCManaged(args[1], args[0], null); ipcmanager.Start(); app.Run(); @@ -68,5 +78,27 @@ namespace Microsoft.PowerToys.Settings.UI.Runner { return ipcmanager; } + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); + + internal static void WaitForPowerToysRunner() + { + Task.Run(() => + { + const uint INFINITE = 0xFFFFFFFF; + const uint WAIT_OBJECT_0 = 0x00000000; + const uint SYNCHRONIZE = 0x00100000; + + IntPtr powerToysProcHandle = OpenProcess(SYNCHRONIZE, false, PowerToysPID); + if (WaitForSingleObject(powerToysProcHandle, INFINITE) == WAIT_OBJECT_0) + { + Environment.Exit(0); + } + }); + } } } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs index 35e5fcd8d8..95bd3b13bc 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/App.xaml.cs @@ -2,6 +2,9 @@ // 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.Runtime.InteropServices; +using System.Threading.Tasks; using System.Windows; using FancyZonesEditor.Models; @@ -21,6 +24,8 @@ namespace FancyZonesEditor private void OnStartup(object sender, StartupEventArgs e) { + WaitForPowerToysRunner(); + LayoutModel foundModel = null; foreach (LayoutModel model in ZoneSettings.DefaultModels) @@ -57,5 +62,27 @@ namespace FancyZonesEditor overlay.Show(); overlay.DataContext = foundModel; } + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); + + private void WaitForPowerToysRunner() + { + Task.Run(() => + { + const uint INFINITE = 0xFFFFFFFF; + const uint WAIT_OBJECT_0 = 0x00000000; + const uint SYNCHRONIZE = 0x00100000; + + IntPtr powerToysProcHandle = OpenProcess(SYNCHRONIZE, false, Settings.PowerToysPID); + if (WaitForSingleObject(powerToysProcHandle, INFINITE) == WAIT_OBJECT_0) + { + Environment.Exit(0); + } + }); + } } } diff --git a/src/modules/fancyzones/editor/FancyZonesEditor/Models/Settings.cs b/src/modules/fancyzones/editor/FancyZonesEditor/Models/Settings.cs index a6f2f98c5f..f92dc2bc5b 100644 --- a/src/modules/fancyzones/editor/FancyZonesEditor/Models/Settings.cs +++ b/src/modules/fancyzones/editor/FancyZonesEditor/Models/Settings.cs @@ -25,6 +25,7 @@ namespace FancyZonesEditor ActiveZoneSetTmpFile, AppliedZoneSetTmpFile, CustomZoneSetsTmpFile, + PowerToysPID, } private static CanvasLayoutModel _blankCustomModel; @@ -242,6 +243,13 @@ namespace FancyZonesEditor private static string _customZoneSetsTmpFile; + public static int PowerToysPID + { + get { return _powerToysPID; } + } + + private static int _powerToysPID; + // UpdateLayoutModels // Update the five default layouts based on the new ZoneCount private void UpdateLayoutModels() @@ -410,7 +418,7 @@ namespace FancyZonesEditor WorkArea = SystemParameters.WorkArea; string[] args = Environment.GetCommandLineArgs(); - if (args.Length == 5) + if (args.Length == 6) { var parsedLocation = args[(int)CmdArgs.X_Y_Width_Height].Split('_'); var x = int.Parse(parsedLocation[0]); @@ -424,6 +432,8 @@ namespace FancyZonesEditor _appliedZoneSetTmpFile = args[(int)CmdArgs.AppliedZoneSetTmpFile]; _customZoneSetsTmpFile = args[(int)CmdArgs.CustomZoneSetsTmpFile]; + int.TryParse(args[(int)CmdArgs.PowerToysPID], out _powerToysPID); + ParseDeviceInfoData(); } } diff --git a/src/modules/fancyzones/lib/FancyZones.cpp b/src/modules/fancyzones/lib/FancyZones.cpp index 49de74745b..9706e4633b 100644 --- a/src/modules/fancyzones/lib/FancyZones.cpp +++ b/src/modules/fancyzones/lib/FancyZones.cpp @@ -485,7 +485,8 @@ void FancyZones::ToggleEditor() noexcept /*1*/ editorLocation + L" " + /*2*/ L"\"" + ZoneWindowUtils::GetActiveZoneSetTmpPath() + L"\" " + /*3*/ L"\"" + ZoneWindowUtils::GetAppliedZoneSetTmpPath() + L"\" " + - /*4*/ L"\"" + ZoneWindowUtils::GetCustomZoneSetsTmpPath() + L"\""; + /*4*/ L"\"" + ZoneWindowUtils::GetCustomZoneSetsTmpPath() + L"\" " + + /*5*/ L"\"" + std::to_wstring(GetCurrentProcessId()) + L"\""; SHELLEXECUTEINFO sei{ sizeof(sei) }; sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI }; diff --git a/src/modules/launcher/Microsoft.Launcher/dllmain.cpp b/src/modules/launcher/Microsoft.Launcher/dllmain.cpp index 9291cdc961..42e0db209f 100644 --- a/src/modules/launcher/Microsoft.Launcher/dllmain.cpp +++ b/src/modules/launcher/Microsoft.Launcher/dllmain.cpp @@ -132,12 +132,18 @@ public: // Enable the powertoy virtual void enable() { + unsigned long powertoys_pid = GetCurrentProcessId(); + if (!is_process_elevated(false)) { + 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"modules\\launcher\\PowerLauncher.exe"; sei.nShow = SW_SHOWNORMAL; + sei.lpParameters = executable_args.data(); ShellExecuteExW(&sei); m_hProcess = sei.hProcess; @@ -151,6 +157,7 @@ public: params += L"-target modules\\launcher\\PowerLauncher.exe "; params += L"-pidFile "; params += POWER_LAUNCHER_PID_SHARED_FILE; + params += L" " + std::to_wstring(powertoys_pid) + L" "; action_runner_path += L"\\action_runner.exe"; // Set up the shared file from which to retrieve the PID of PowerLauncher diff --git a/src/modules/launcher/PowerLauncher/App.xaml.cs b/src/modules/launcher/PowerLauncher/App.xaml.cs index 3028af9cf3..278f394513 100644 --- a/src/modules/launcher/PowerLauncher/App.xaml.cs +++ b/src/modules/launcher/PowerLauncher/App.xaml.cs @@ -2,6 +2,7 @@ using Microsoft.PowerLauncher.Telemetry; using Microsoft.PowerToys.Telemetry; using System; using System.Diagnostics; +using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Timers; using System.Windows; @@ -20,13 +21,12 @@ using Stopwatch = Wox.Infrastructure.Stopwatch; namespace PowerLauncher { - - public partial class App : IDisposable, ISingleInstanceApp { public static PublicAPIInstance API { get; private set; } private const string Unique = "PowerLauncher_Unique_Application_Mutex"; private static bool _disposed; + private static int _powerToysPid; private Settings _settings; private MainViewModel _mainVM; private SettingWindowViewModel _settingsVM; @@ -35,10 +35,12 @@ namespace PowerLauncher private SettingsWatcher _settingsWatcher; [STAThread] - public static void Main() + public static void Main(string[] args) { if (SingleInstance.InitializeAsFirstInstance(Unique)) { + int.TryParse(args[0], out _powerToysPid); + using (var application = new App()) { application.InitializeComponent(); @@ -49,6 +51,8 @@ namespace PowerLauncher private void OnStartup(object sender, StartupEventArgs e) { + WaitForPowerToysRunner(); + var bootTime = new System.Diagnostics.Stopwatch(); bootTime.Start(); Stopwatch.Normal("|App.OnStartup|Startup cost", () => @@ -113,6 +117,28 @@ namespace PowerLauncher Current.SessionEnding += (s, e) => Dispose(); } + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds); + + private void WaitForPowerToysRunner() + { + Task.Run(() => + { + const uint INFINITE = 0xFFFFFFFF; + const uint WAIT_OBJECT_0 = 0x00000000; + const uint SYNCHRONIZE = 0x00100000; + + IntPtr powerToysProcHandle = OpenProcess(SYNCHRONIZE, false, _powerToysPid); + if (WaitForSingleObject(powerToysProcHandle, INFINITE) == WAIT_OBJECT_0) + { + Environment.Exit(0); + } + }); + } + /// /// let exception throw as normal is better for Debug ///