-
Notifications
You must be signed in to change notification settings - Fork 6.9k
/
Copy pathRunnerHelper.cs
91 lines (77 loc) · 3.59 KB
/
RunnerHelper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// 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.Reflection;
using System.Threading.Tasks;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace ManagedCommon
{
public static class RunnerHelper
{
public static void WaitForPowerToysRunner(int powerToysPID, Action act, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "")
{
var stackTrace = new StackTrace();
var assembly = Assembly.GetCallingAssembly().GetName();
PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{memberName}]WaitForPowerToysRunner waiting for Event powerToysPID={powerToysPID}" });
Task.Run(() =>
{
const uint INFINITE = 0xFFFFFFFF;
const uint WAIT_OBJECT_0 = 0x00000000;
const uint SYNCHRONIZE = 0x00100000;
IntPtr powerToysProcHandle = NativeMethods.OpenProcess(SYNCHRONIZE, false, powerToysPID);
if (NativeMethods.WaitForSingleObject(powerToysProcHandle, INFINITE) == WAIT_OBJECT_0)
{
PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{memberName}]WaitForPowerToysRunner Event Notified powerToysPID={powerToysPID}" });
act.Invoke();
}
});
}
private static readonly string PowerToysRunnerProcessName = "PowerToys.exe";
// In case we don't have a permission to open user's processes with a SYNCHRONIZE access right, e.g. LocalSystem processes, we could use GetExitCodeProcess to check the process' exit code periodically.
public static void WaitForPowerToysRunnerExitFallback(Action act)
{
int[] processIds = new int[1024];
uint bytesCopied;
NativeMethods.EnumProcesses(processIds, (uint)processIds.Length * sizeof(uint), out bytesCopied);
const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000;
var handleAccess = PROCESS_QUERY_LIMITED_INFORMATION;
IntPtr runnerHandle = IntPtr.Zero;
foreach (var processId in processIds)
{
IntPtr hProcess = NativeMethods.OpenProcess(handleAccess, false, processId);
System.Text.StringBuilder name = new System.Text.StringBuilder(1024);
uint length = 1024;
if (hProcess == IntPtr.Zero || !NativeMethods.QueryFullProcessImageName(hProcess, 0, name, ref length))
{
continue;
}
if (System.IO.Path.GetFileName(name.ToString()) == PowerToysRunnerProcessName)
{
runnerHandle = hProcess;
break;
}
}
if (runnerHandle == IntPtr.Zero)
{
Logger.LogError("Couldn't determine PowerToys.exe pid");
return;
}
Task.Run(() =>
{
const int STILL_ACTIVE = 0x103;
uint exit_status;
do
{
System.Threading.Thread.Sleep(1000);
NativeMethods.GetExitCodeProcess(runnerHandle, out exit_status);
}
while (exit_status == STILL_ACTIVE);
NativeMethods.CloseHandle(runnerHandle);
act.Invoke();
});
}
}
}