[PowerToys Run] Issues with elevation (#11775)

* Delegate creation of non elevated process

* Error handling

* nits

* Fix potential race condition

* Fix spelling

* Fix spelling

* Fix build
This commit is contained in:
Mykhailo Pylyp
2021-06-22 15:24:03 +03:00
committed by GitHub
parent 7e79654ee0
commit cf9f0ce6a9
6 changed files with 215 additions and 113 deletions

View File

@@ -6,6 +6,7 @@ using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using interop;
using ManagedCommon;
@@ -43,34 +44,46 @@ namespace PowerLauncher
public static void Main()
{
Log.Info($"Starting PowerToys Run with PID={Process.GetCurrentProcess().Id}", typeof(App));
if (SingleInstance<App>.InitializeAsFirstInstance())
int powerToysPid = GetPowerToysPId();
if (powerToysPid != 0)
{
using (var application = new App())
{
application.InitializeComponent();
NativeEventWaiter.WaitForEventLoop(Constants.RunExitEvent(), () =>
{
Log.Warn("RunExitEvent was signaled. Exiting PowerToys", typeof(App));
ExitPowerToys(application);
});
int powerToysPid = GetPowerToysPId();
if (powerToysPid != 0)
{
Log.Info($"Runner pid={powerToysPid}", typeof(App));
RunnerHelper.WaitForPowerToysRunner(powerToysPid, () =>
{
Log.Info($"Runner with pid={powerToysPid} exited. Exiting PowerToys Run", typeof(App));
ExitPowerToys(application);
});
}
application.Run();
}
// 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
{
Log.Error("There is already running PowerToys Run instance. Exiting PowerToys Run", typeof(App));
// 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(() =>
{
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);
});
}
application.Run();
}
}

View File

@@ -44,12 +44,18 @@ namespace PowerLauncher.Helper
/// Suffix to the channel name.
/// </summary>
private const string ChannelNameSuffix = "SingeInstanceIPCChannel";
private const string InstanceMutexName = @"Local\PowerToys_Run_InstanceMutex";
/// <summary>
/// Gets or sets application mutex.
/// </summary>
internal static Mutex SingleInstanceMutex { get; set; }
internal static void CreateInstanceMutex()
{
SingleInstanceMutex = new Mutex(true, InstanceMutexName, out bool firstInstance);
}
/// <summary>
/// Checks if the instance of the application attempting to start is the first instance.
/// If not, activates the first instance.
@@ -57,14 +63,12 @@ namespace PowerLauncher.Helper
/// <returns>True if this is the first instance of the application.</returns>
internal static bool InitializeAsFirstInstance()
{
string mutexName = @"Local\PowerToys_Run_InstanceMutex";
// Build unique application Id and the IPC channel name.
string applicationIdentifier = mutexName + Environment.UserName;
string applicationIdentifier = InstanceMutexName + Environment.UserName;
string channelName = string.Concat(applicationIdentifier, Delimiter, ChannelNameSuffix);
SingleInstanceMutex = new Mutex(true, mutexName, out bool firstInstance);
SingleInstanceMutex = new Mutex(true, InstanceMutexName, out bool firstInstance);
if (firstInstance)
{
_ = CreateRemoteService(channelName);