mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 19:57:57 +01:00
Don't use Environment.Exit (#20532)
* [Awake] Don't use Process.Exit and move to CsWin32 * [PowerLauncher] Remove unused API * [ColorPicker] Use cancellable NativeEventWaiter + cleanup using * [TextExtractor] Don't use Environment.Exit * [MeasureTool] Don't use Environment.Exit(0); * [FZE] don't use Environment.Exit and fix WaitForPowerToysRunner
This commit is contained in:
15
.github/actions/spell-check/expect.txt
vendored
15
.github/actions/spell-check/expect.txt
vendored
@@ -60,7 +60,6 @@ APeriod
|
|||||||
api
|
api
|
||||||
APIENTRY
|
APIENTRY
|
||||||
APIIs
|
APIIs
|
||||||
Apm
|
|
||||||
APPBARDATA
|
APPBARDATA
|
||||||
appdata
|
appdata
|
||||||
APPICON
|
APPICON
|
||||||
@@ -130,7 +129,6 @@ Avanc
|
|||||||
Awaitable
|
Awaitable
|
||||||
awakeness
|
awakeness
|
||||||
awakeversion
|
awakeversion
|
||||||
AWAYMODE
|
|
||||||
AYUV
|
AYUV
|
||||||
backend
|
backend
|
||||||
backtracer
|
backtracer
|
||||||
@@ -498,7 +496,6 @@ dvr
|
|||||||
DVSD
|
DVSD
|
||||||
DVSL
|
DVSL
|
||||||
DVTARGETDEVICE
|
DVTARGETDEVICE
|
||||||
dwhkl
|
|
||||||
DWINRT
|
DWINRT
|
||||||
dwl
|
dwl
|
||||||
dwm
|
dwm
|
||||||
@@ -728,8 +725,6 @@ hhk
|
|||||||
HHmmss
|
HHmmss
|
||||||
HHOOK
|
HHOOK
|
||||||
hhx
|
hhx
|
||||||
Hiber
|
|
||||||
Hiberboot
|
|
||||||
HIBYTE
|
HIBYTE
|
||||||
HICON
|
HICON
|
||||||
HIDEWINDOW
|
HIDEWINDOW
|
||||||
@@ -907,7 +902,6 @@ inheritdoc
|
|||||||
initguid
|
initguid
|
||||||
Inkscape
|
Inkscape
|
||||||
Inlines
|
Inlines
|
||||||
Inlining
|
|
||||||
inorder
|
inorder
|
||||||
INotification
|
INotification
|
||||||
INotify
|
INotify
|
||||||
@@ -1037,7 +1031,6 @@ jxr
|
|||||||
jyuwono
|
jyuwono
|
||||||
KBDLLHOOKSTRUCT
|
KBDLLHOOKSTRUCT
|
||||||
kbm
|
kbm
|
||||||
KCode
|
|
||||||
KEYBDINPUT
|
KEYBDINPUT
|
||||||
keybindings
|
keybindings
|
||||||
keyboardeventhandlers
|
keyboardeventhandlers
|
||||||
@@ -1161,7 +1154,6 @@ lpsz
|
|||||||
lpt
|
lpt
|
||||||
LPTHREAD
|
LPTHREAD
|
||||||
LPTOP
|
LPTOP
|
||||||
lptpm
|
|
||||||
LPTSTR
|
LPTSTR
|
||||||
LPVOID
|
LPVOID
|
||||||
LPW
|
LPW
|
||||||
@@ -1226,7 +1218,6 @@ Melman
|
|||||||
memcmp
|
memcmp
|
||||||
memcpy
|
memcpy
|
||||||
memset
|
memset
|
||||||
MENUBREAK
|
|
||||||
MENUITEMINFO
|
MENUITEMINFO
|
||||||
MENUITEMINFOW
|
MENUITEMINFOW
|
||||||
Metadatas
|
Metadatas
|
||||||
@@ -1432,7 +1423,6 @@ ntdll
|
|||||||
NTFS
|
NTFS
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
nuget
|
nuget
|
||||||
nuint
|
|
||||||
nullonfailure
|
nullonfailure
|
||||||
nullopt
|
nullopt
|
||||||
nullptr
|
nullptr
|
||||||
@@ -1494,7 +1484,6 @@ overlaywindow
|
|||||||
Overridable
|
Overridable
|
||||||
Oversampling
|
Oversampling
|
||||||
OWNDC
|
OWNDC
|
||||||
OWNERDRAW
|
|
||||||
PACL
|
PACL
|
||||||
pagos
|
pagos
|
||||||
PAINTSTRUCT
|
PAINTSTRUCT
|
||||||
@@ -1536,6 +1525,7 @@ pfo
|
|||||||
pft
|
pft
|
||||||
pgp
|
pgp
|
||||||
pguid
|
pguid
|
||||||
|
PHANDLER
|
||||||
phbm
|
phbm
|
||||||
phbmp
|
phbmp
|
||||||
phwnd
|
phwnd
|
||||||
@@ -1938,6 +1928,7 @@ sse
|
|||||||
ssf
|
ssf
|
||||||
ssh
|
ssh
|
||||||
sstream
|
sstream
|
||||||
|
stackalloc
|
||||||
STACKFRAME
|
STACKFRAME
|
||||||
stackoverflow
|
stackoverflow
|
||||||
stackpanel
|
stackpanel
|
||||||
@@ -2237,14 +2228,12 @@ VIDEOINFOHEADER
|
|||||||
viewbox
|
viewbox
|
||||||
viewmodel
|
viewmodel
|
||||||
vih
|
vih
|
||||||
Virt
|
|
||||||
virtualization
|
virtualization
|
||||||
Virtualizing
|
Virtualizing
|
||||||
visiblecolorformats
|
visiblecolorformats
|
||||||
Visibletrue
|
Visibletrue
|
||||||
visualbrush
|
visualbrush
|
||||||
visualstudio
|
visualstudio
|
||||||
viter
|
|
||||||
VKey
|
VKey
|
||||||
VKTAB
|
VKTAB
|
||||||
vmovl
|
vmovl
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using ControlzEx.Theming;
|
using ControlzEx.Theming;
|
||||||
|
|
||||||
namespace Common.UI
|
namespace Common.UI
|
||||||
|
|||||||
@@ -3,26 +3,24 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
|
||||||
using Wox.Plugin.Logger;
|
|
||||||
|
|
||||||
namespace PowerLauncher.Helper
|
using Dispatcher = System.Windows.Threading.Dispatcher;
|
||||||
|
|
||||||
|
namespace Common.UI
|
||||||
{
|
{
|
||||||
public static class NativeEventWaiter
|
public static class NativeEventWaiter
|
||||||
{
|
{
|
||||||
public static void WaitForEventLoop(string eventName, Action callback, CancellationToken cancel)
|
public static void WaitForEventLoop(string eventName, Action callback, Dispatcher dispatcher, CancellationToken cancel)
|
||||||
{
|
{
|
||||||
new Thread(() =>
|
new Thread(() =>
|
||||||
{
|
{
|
||||||
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
|
var eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset, eventName);
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (WaitHandle.WaitAny(new WaitHandle[] { cancel.WaitHandle, eventHandle }) == 1)
|
if (WaitHandle.WaitAny(new WaitHandle[] { cancel.WaitHandle, eventHandle }) == 1)
|
||||||
{
|
{
|
||||||
Log.Info($"Successfully waited for {eventName}", MethodBase.GetCurrentMethod().DeclaringType);
|
dispatcher.BeginInvoke(callback);
|
||||||
Application.Current.Dispatcher.Invoke(callback);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
using MeasureToolUI.Helpers;
|
using MeasureToolUI.Helpers;
|
||||||
|
using Microsoft.UI.Dispatching;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
|
|
||||||
namespace MeasureToolUI
|
namespace MeasureToolUI
|
||||||
@@ -36,9 +37,10 @@ namespace MeasureToolUI
|
|||||||
{
|
{
|
||||||
if (int.TryParse(cmdArgs[cmdArgs.Length - 1], out int powerToysRunnerPid))
|
if (int.TryParse(cmdArgs[cmdArgs.Length - 1], out int powerToysRunnerPid))
|
||||||
{
|
{
|
||||||
|
var dispatcher = DispatcherQueue.GetForCurrentThread();
|
||||||
RunnerHelper.WaitForPowerToysRunner(powerToysRunnerPid, () =>
|
RunnerHelper.WaitForPowerToysRunner(powerToysRunnerPid, () =>
|
||||||
{
|
{
|
||||||
Environment.Exit(0);
|
dispatcher.TryEnqueue(App.Current.Exit);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +53,8 @@ namespace MeasureToolUI
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError($"MeasureToolCore failed to initialize: {ex}");
|
Logger.LogError($"MeasureToolCore failed to initialize: {ex}");
|
||||||
Environment.Exit(1);
|
App.Current.Exit();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_window = new MainWindow(core);
|
_window = new MainWindow(core);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
@@ -23,6 +22,13 @@ public partial class App : Application, IDisposable
|
|||||||
private Mutex? _instanceMutex;
|
private Mutex? _instanceMutex;
|
||||||
private int _powerToysRunnerPid;
|
private int _powerToysRunnerPid;
|
||||||
|
|
||||||
|
private CancellationTokenSource NativeThreadCTS { get; set; }
|
||||||
|
|
||||||
|
public App()
|
||||||
|
{
|
||||||
|
NativeThreadCTS = new CancellationTokenSource();
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
@@ -37,7 +43,7 @@ public partial class App : Application, IDisposable
|
|||||||
{
|
{
|
||||||
Logger.LogWarning("Another running TextExtractor instance was detected. Exiting TextExtractor");
|
Logger.LogWarning("Another running TextExtractor instance was detected. Exiting TextExtractor");
|
||||||
_instanceMutex = null;
|
_instanceMutex = null;
|
||||||
Environment.Exit(0);
|
Shutdown();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,10 +57,11 @@ public partial class App : Application, IDisposable
|
|||||||
RunnerHelper.WaitForPowerToysRunner(_powerToysRunnerPid, () =>
|
RunnerHelper.WaitForPowerToysRunner(_powerToysRunnerPid, () =>
|
||||||
{
|
{
|
||||||
Logger.LogInfo("PowerToys Runner exited. Exiting TextExtractor");
|
Logger.LogInfo("PowerToys Runner exited. Exiting TextExtractor");
|
||||||
Environment.Exit(0);
|
NativeThreadCTS.Cancel();
|
||||||
|
Application.Current.Dispatcher.Invoke(() => Shutdown());
|
||||||
});
|
});
|
||||||
var userSettings = new UserSettings(new Helpers.ThrottledActionInvoker());
|
var userSettings = new UserSettings(new Helpers.ThrottledActionInvoker());
|
||||||
eventMonitor = new EventMonitor();
|
eventMonitor = new EventMonitor(Application.Current.Dispatcher, NativeThreadCTS.Token);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
// 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.Threading;
|
|
||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace PowerOCR.Helpers
|
|
||||||
{
|
|
||||||
public static class NativeEventWaiter
|
|
||||||
{
|
|
||||||
public static void WaitForEventLoop(string eventName, Action callback)
|
|
||||||
{
|
|
||||||
new Thread(() =>
|
|
||||||
{
|
|
||||||
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (eventHandle.WaitOne())
|
|
||||||
{
|
|
||||||
Logger.LogInfo($"Successfully waited for {eventName}");
|
|
||||||
Application.Current.Dispatcher.Invoke(callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
|
using Common.UI;
|
||||||
using interop;
|
using interop;
|
||||||
using PowerOCR.Helpers;
|
using PowerOCR.Helpers;
|
||||||
using PowerOCR.Utilities;
|
using PowerOCR.Utilities;
|
||||||
@@ -16,9 +17,9 @@ namespace PowerOCR.Keyboard
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal class EventMonitor
|
internal class EventMonitor
|
||||||
{
|
{
|
||||||
public EventMonitor()
|
public EventMonitor(System.Windows.Threading.Dispatcher dispatcher, System.Threading.CancellationToken exitToken)
|
||||||
{
|
{
|
||||||
NativeEventWaiter.WaitForEventLoop(Constants.ShowPowerOCRSharedEvent(), StartOCRSession);
|
NativeEventWaiter.WaitForEventLoop(Constants.ShowPowerOCRSharedEvent(), StartOCRSession, dispatcher, exitToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartOCRSession()
|
public void StartOCRSession()
|
||||||
|
|||||||
@@ -43,6 +43,9 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="NLog" Version="4.7.13" />
|
<PackageReference Include="NLog" Version="4.7.13" />
|
||||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20071.2" />
|
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20071.2" />
|
||||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||||
|
|||||||
@@ -7,17 +7,20 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
using Awake.Core.Models;
|
using Awake.Core.Models;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using Windows.Win32;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.Storage.FileSystem;
|
||||||
|
using Windows.Win32.System.Console;
|
||||||
|
using Windows.Win32.System.Power;
|
||||||
|
|
||||||
namespace Awake.Core
|
namespace Awake.Core
|
||||||
{
|
{
|
||||||
public delegate bool ConsoleEventHandler(ControlType ctrlType);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper class that allows talking to Win32 APIs without having to rely on PInvoke in other parts
|
/// Helper class that allows talking to Win32 APIs without having to rely on PInvoke in other parts
|
||||||
/// of the codebase.
|
/// of the codebase.
|
||||||
@@ -25,9 +28,6 @@ namespace Awake.Core
|
|||||||
public class APIHelper
|
public class APIHelper
|
||||||
{
|
{
|
||||||
private const string BuildRegistryLocation = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
|
private const string BuildRegistryLocation = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
|
||||||
private const int StdOutputHandle = -11;
|
|
||||||
private const uint GenericWrite = 0x40000000;
|
|
||||||
private const uint GenericRead = 0x80000000;
|
|
||||||
|
|
||||||
private static readonly Logger _log;
|
private static readonly Logger _log;
|
||||||
private static CancellationTokenSource _tokenSource;
|
private static CancellationTokenSource _tokenSource;
|
||||||
@@ -43,21 +43,21 @@ namespace Awake.Core
|
|||||||
_tokenSource = new CancellationTokenSource();
|
_tokenSource = new CancellationTokenSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetConsoleControlHandler(ConsoleEventHandler handler, bool addHandler)
|
internal static void SetConsoleControlHandler(PHANDLER_ROUTINE handler, bool addHandler)
|
||||||
{
|
{
|
||||||
NativeMethods.SetConsoleCtrlHandler(handler, addHandler);
|
PInvoke.SetConsoleCtrlHandler(handler, addHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AllocateConsole()
|
public static void AllocateConsole()
|
||||||
{
|
{
|
||||||
_log.Debug("Bootstrapping the console allocation routine.");
|
_log.Debug("Bootstrapping the console allocation routine.");
|
||||||
NativeMethods.AllocConsole();
|
PInvoke.AllocConsole();
|
||||||
_log.Debug($"Console allocation result: {Marshal.GetLastWin32Error()}");
|
_log.Debug($"Console allocation result: {Marshal.GetLastWin32Error()}");
|
||||||
|
|
||||||
var outputFilePointer = NativeMethods.CreateFile("CONOUT$", GenericRead | GenericWrite, FileShare.Write, IntPtr.Zero, FileMode.OpenOrCreate, 0, IntPtr.Zero);
|
var outputFilePointer = PInvoke.CreateFile("CONOUT$", FILE_ACCESS_FLAGS.FILE_GENERIC_READ | FILE_ACCESS_FLAGS.FILE_GENERIC_WRITE, FILE_SHARE_MODE.FILE_SHARE_WRITE, null, FILE_CREATION_DISPOSITION.OPEN_EXISTING, 0, null);
|
||||||
_log.Debug($"CONOUT creation result: {Marshal.GetLastWin32Error()}");
|
_log.Debug($"CONOUT creation result: {Marshal.GetLastWin32Error()}");
|
||||||
|
|
||||||
NativeMethods.SetStdHandle(StdOutputHandle, outputFilePointer);
|
PInvoke.SetStdHandle(Windows.Win32.System.Console.STD_HANDLE.STD_OUTPUT_HANDLE, outputFilePointer);
|
||||||
_log.Debug($"SetStdHandle result: {Marshal.GetLastWin32Error()}");
|
_log.Debug($"SetStdHandle result: {Marshal.GetLastWin32Error()}");
|
||||||
|
|
||||||
Console.SetOut(new StreamWriter(Console.OpenStandardOutput(), Console.OutputEncoding) { AutoFlush = true });
|
Console.SetOut(new StreamWriter(Console.OpenStandardOutput(), Console.OutputEncoding) { AutoFlush = true });
|
||||||
@@ -70,11 +70,11 @@ namespace Awake.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">Single or multiple EXECUTION_STATE entries.</param>
|
/// <param name="state">Single or multiple EXECUTION_STATE entries.</param>
|
||||||
/// <returns>true if successful, false if failed</returns>
|
/// <returns>true if successful, false if failed</returns>
|
||||||
private static bool SetAwakeState(ExecutionState state)
|
private static bool SetAwakeState(EXECUTION_STATE state)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var stateResult = NativeMethods.SetThreadExecutionState(state);
|
var stateResult = PInvoke.SetThreadExecutionState(state);
|
||||||
return stateResult != 0;
|
return stateResult != 0;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -160,18 +160,18 @@ namespace Awake.Core
|
|||||||
bool success;
|
bool success;
|
||||||
if (keepDisplayOn)
|
if (keepDisplayOn)
|
||||||
{
|
{
|
||||||
success = SetAwakeState(ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_CONTINUOUS);
|
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
success = SetAwakeState(ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_CONTINUOUS);
|
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
_log.Info($"Initiated indefinite keep awake in background thread: {NativeMethods.GetCurrentThreadId()}. Screen on: {keepDisplayOn}");
|
_log.Info($"Initiated indefinite keep awake in background thread: {PInvoke.GetCurrentThreadId()}. Screen on: {keepDisplayOn}");
|
||||||
|
|
||||||
WaitHandle.WaitAny(new[] { _threadToken.WaitHandle });
|
WaitHandle.WaitAny(new[] { _threadToken.WaitHandle });
|
||||||
|
|
||||||
@@ -186,28 +186,35 @@ namespace Awake.Core
|
|||||||
catch (OperationCanceledException ex)
|
catch (OperationCanceledException ex)
|
||||||
{
|
{
|
||||||
// Task was clearly cancelled.
|
// Task was clearly cancelled.
|
||||||
_log.Info($"Background thread termination: {NativeMethods.GetCurrentThreadId()}. Message: {ex.Message}");
|
_log.Info($"Background thread termination: {PInvoke.GetCurrentThreadId()}. Message: {ex.Message}");
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void CompleteExit(int exitCode, bool force = false)
|
internal static void CompleteExit(int exitCode, ManualResetEvent? exitSignal, bool force = false)
|
||||||
{
|
{
|
||||||
APIHelper.SetNoKeepAwake();
|
SetNoKeepAwake();
|
||||||
TrayHelper.ClearTray();
|
|
||||||
|
|
||||||
// Because we are running a message loop for the tray, we can't just use Environment.Exit,
|
HWND windowHandle = GetHiddenWindow();
|
||||||
// but have to make sure that we properly send the termination message.
|
|
||||||
IntPtr windowHandle = APIHelper.GetHiddenWindow();
|
|
||||||
|
|
||||||
if (windowHandle != IntPtr.Zero)
|
if (windowHandle != HWND.Null)
|
||||||
{
|
{
|
||||||
NativeMethods.SendMessage(windowHandle, NativeConstants.WM_CLOSE, 0, string.Empty);
|
PInvoke.SendMessage(windowHandle, PInvoke.WM_CLOSE, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force)
|
if (force)
|
||||||
{
|
{
|
||||||
Environment.Exit(exitCode);
|
PInvoke.PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
exitSignal?.Set();
|
||||||
|
PInvoke.DestroyWindow(windowHandle);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Info($"Exit signal error ${ex}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,18 +228,18 @@ namespace Awake.Core
|
|||||||
{
|
{
|
||||||
if (keepDisplayOn)
|
if (keepDisplayOn)
|
||||||
{
|
{
|
||||||
success = SetAwakeState(ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_DISPLAY_REQUIRED | ExecutionState.ES_CONTINUOUS);
|
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
success = SetAwakeState(ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_CONTINUOUS);
|
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
_log.Info($"Initiated temporary keep awake in background thread: {NativeMethods.GetCurrentThreadId()}. Screen on: {keepDisplayOn}");
|
_log.Info($"Initiated temporary keep awake in background thread: {PInvoke.GetCurrentThreadId()}. Screen on: {keepDisplayOn}");
|
||||||
|
|
||||||
_timedLoopTimer = new System.Timers.Timer(seconds * 1000);
|
_timedLoopTimer = new System.Timers.Timer((seconds * 1000) + 1);
|
||||||
_timedLoopTimer.Elapsed += (s, e) =>
|
_timedLoopTimer.Elapsed += (s, e) =>
|
||||||
{
|
{
|
||||||
_tokenSource.Cancel();
|
_tokenSource.Cancel();
|
||||||
@@ -262,7 +269,7 @@ namespace Awake.Core
|
|||||||
catch (OperationCanceledException ex)
|
catch (OperationCanceledException ex)
|
||||||
{
|
{
|
||||||
// Task was clearly cancelled.
|
// Task was clearly cancelled.
|
||||||
_log.Info($"Background thread termination: {NativeMethods.GetCurrentThreadId()}. Message: {ex.Message}");
|
_log.Info($"Background thread termination: {PInvoke.GetCurrentThreadId()}. Message: {ex.Message}");
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,15 +301,20 @@ namespace Awake.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
[SuppressMessage("Performance", "CA1806:Do not ignore method results", Justification = "Function returns DWORD value that identifies the current thread, but we do not need it.")]
|
[SuppressMessage("Performance", "CA1806:Do not ignore method results", Justification = "Function returns DWORD value that identifies the current thread, but we do not need it.")]
|
||||||
public static IEnumerable<IntPtr> EnumerateWindowsForProcess(int processId)
|
internal static IEnumerable<HWND> EnumerateWindowsForProcess(int processId)
|
||||||
{
|
{
|
||||||
var handles = new List<IntPtr>();
|
var handles = new List<HWND>();
|
||||||
IntPtr hCurrentWnd = IntPtr.Zero;
|
var hCurrentWnd = HWND.Null;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
hCurrentWnd = NativeMethods.FindWindowEx(IntPtr.Zero, hCurrentWnd, null, null);
|
hCurrentWnd = PInvoke.FindWindowEx(HWND.Null, hCurrentWnd, null as string, null);
|
||||||
NativeMethods.GetWindowThreadProcessId(hCurrentWnd, out uint targetProcessId);
|
uint targetProcessId = 0;
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
PInvoke.GetWindowThreadProcessId(hCurrentWnd, &targetProcessId);
|
||||||
|
}
|
||||||
|
|
||||||
if (targetProcessId == processId)
|
if (targetProcessId == processId)
|
||||||
{
|
{
|
||||||
handles.Add(hCurrentWnd);
|
handles.Add(hCurrentWnd);
|
||||||
@@ -314,23 +326,30 @@ namespace Awake.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
[SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "In this context, the string is only converted to a hex value.")]
|
[SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "In this context, the string is only converted to a hex value.")]
|
||||||
public static IntPtr GetHiddenWindow()
|
internal static HWND GetHiddenWindow()
|
||||||
{
|
{
|
||||||
IEnumerable<IntPtr> windowHandles = EnumerateWindowsForProcess(Environment.ProcessId);
|
IEnumerable<HWND> windowHandles = EnumerateWindowsForProcess(Environment.ProcessId);
|
||||||
var domain = AppDomain.CurrentDomain.GetHashCode().ToString("x");
|
var domain = AppDomain.CurrentDomain.GetHashCode().ToString("x");
|
||||||
string targetClass = $"{InternalConstants.TrayWindowId}{domain}";
|
string targetClass = $"{InternalConstants.TrayWindowId}{domain}";
|
||||||
|
|
||||||
foreach (var handle in windowHandles)
|
unsafe
|
||||||
{
|
{
|
||||||
StringBuilder className = new (256);
|
var classNameLen = 256;
|
||||||
int classQueryResult = NativeMethods.GetClassName(handle, className, className.Capacity);
|
Span<char> className = stackalloc char[classNameLen];
|
||||||
if (classQueryResult != 0 && className.ToString().StartsWith(targetClass, StringComparison.InvariantCultureIgnoreCase))
|
foreach (var handle in windowHandles)
|
||||||
{
|
{
|
||||||
return handle;
|
fixed (char* ptr = className)
|
||||||
|
{
|
||||||
|
int classQueryResult = PInvoke.GetClassName(handle, ptr, classNameLen);
|
||||||
|
if (classQueryResult != 0 && className.ToString().StartsWith(targetClass, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return IntPtr.Zero;
|
return HWND.Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, int> GetDefaultTrayOptions()
|
public static Dictionary<string, int> GetDefaultTrayOptions()
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
// 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;
|
|
||||||
|
|
||||||
namespace Awake.Core.Models
|
|
||||||
{
|
|
||||||
[Flags]
|
|
||||||
public enum ExecutionState : uint
|
|
||||||
{
|
|
||||||
ES_AWAYMODE_REQUIRED = 0x00000040,
|
|
||||||
ES_CONTINUOUS = 0x80000000,
|
|
||||||
ES_DISPLAY_REQUIRED = 0x00000002,
|
|
||||||
ES_SYSTEM_REQUIRED = 0x00000001,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
// 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.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Awake.Core.Models
|
|
||||||
{
|
|
||||||
public struct SystemPowerCapabilities
|
|
||||||
{
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool PowerButtonPresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool SleepButtonPresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool LidPresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool SystemS1;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool SystemS2;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool SystemS3;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool SystemS4;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool SystemS5;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool HiberFilePresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool FullWake;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool VideoDimPresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool ApmPresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool UpsPresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool ThermalControl;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool ProcessorThrottle;
|
|
||||||
public byte ProcessorMinThrottle;
|
|
||||||
public byte ProcessorMaxThrottle;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool FastSystemS4;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool Hiberboot;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool WakeAlarmPresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool AoAc;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool DiskSpinDown;
|
|
||||||
public byte HiberFileType;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool AoAcConnectivitySupported;
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
|
||||||
private readonly byte[] spare3;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool SystemBatteriesPresent;
|
|
||||||
[MarshalAs(UnmanagedType.U1)]
|
|
||||||
public bool BatteriesAreShortTerm;
|
|
||||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
|
|
||||||
public BatteryReportingScale[] BatteryScale;
|
|
||||||
public SystemPowerState AcOnLineWake;
|
|
||||||
public SystemPowerState SoftLidWake;
|
|
||||||
public SystemPowerState RtcWake;
|
|
||||||
public SystemPowerState MinDeviceWakeState;
|
|
||||||
public SystemPowerState DefaultLowLatencyWake;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
namespace Awake.Core.Models
|
|
||||||
{
|
|
||||||
// Maps to the OS power state.
|
|
||||||
// See documentation: https://docs.microsoft.com/windows/win32/power/system-power-states
|
|
||||||
public enum SystemPowerState
|
|
||||||
{
|
|
||||||
PowerSystemUnspecified = 0,
|
|
||||||
PowerSystemWorking = 1,
|
|
||||||
PowerSystemSleeping1 = 2,
|
|
||||||
PowerSystemSleeping2 = 3,
|
|
||||||
PowerSystemSleeping3 = 4,
|
|
||||||
PowerSystemHibernate = 5,
|
|
||||||
PowerSystemShutdown = 6,
|
|
||||||
PowerSystemMaximum = 7,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,14 +2,16 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
|
using Windows.Win32;
|
||||||
|
|
||||||
namespace Awake.Core.Models
|
namespace Awake.Core.Models
|
||||||
{
|
{
|
||||||
internal enum TrayCommands : uint
|
internal enum TrayCommands : uint
|
||||||
{
|
{
|
||||||
TC_DISPLAY_SETTING = NativeConstants.WM_USER + 1,
|
TC_DISPLAY_SETTING = PInvoke.WM_USER + 1,
|
||||||
TC_MODE_PASSIVE = NativeConstants.WM_USER + 2,
|
TC_MODE_PASSIVE = PInvoke.WM_USER + 2,
|
||||||
TC_MODE_INDEFINITE = NativeConstants.WM_USER + 3,
|
TC_MODE_INDEFINITE = PInvoke.WM_USER + 3,
|
||||||
TC_EXIT = NativeConstants.WM_USER + 4,
|
TC_EXIT = PInvoke.WM_USER + 4,
|
||||||
TC_TIME = NativeConstants.WM_USER + 5,
|
TC_TIME = PInvoke.WM_USER + 5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
#pragma warning disable SA1310 // Field names should not contain underscore
|
|
||||||
|
|
||||||
namespace Awake.Core
|
|
||||||
{
|
|
||||||
internal class NativeConstants
|
|
||||||
{
|
|
||||||
internal const uint WM_COMMAND = 0x111;
|
|
||||||
internal const uint WM_USER = 0x400;
|
|
||||||
internal const uint WM_GETTEXT = 0x000D;
|
|
||||||
internal const uint WM_CLOSE = 0x0010;
|
|
||||||
|
|
||||||
// Popup menu constants.
|
|
||||||
internal const uint MF_BYPOSITION = 1024;
|
|
||||||
internal const uint MF_STRING = 0;
|
|
||||||
internal const uint MF_MENUBREAK = 0x00000040;
|
|
||||||
internal const uint MF_SEPARATOR = 0x00000800;
|
|
||||||
internal const uint MF_POPUP = 0x00000010;
|
|
||||||
internal const uint MF_UNCHECKED = 0x00000000;
|
|
||||||
internal const uint MF_CHECKED = 0x00000008;
|
|
||||||
internal const uint MF_OWNERDRAW = 0x00000100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
// 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.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
using Awake.Core.Models;
|
|
||||||
|
|
||||||
namespace Awake.Core
|
|
||||||
{
|
|
||||||
internal static class NativeMethods
|
|
||||||
{
|
|
||||||
internal delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
|
|
||||||
|
|
||||||
[DllImport("Powrprof.dll", SetLastError = true)]
|
|
||||||
internal static extern bool GetPwrCapabilities(out SystemPowerCapabilities lpSystemPowerCapabilities);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
|
||||||
internal static extern bool SetConsoleCtrlHandler(ConsoleEventHandler handler, bool add);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
||||||
internal static extern ExecutionState SetThreadExecutionState(ExecutionState esFlags);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
internal static extern bool AllocConsole();
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
|
||||||
internal static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true)]
|
|
||||||
internal static extern uint GetCurrentThreadId();
|
|
||||||
|
|
||||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
||||||
internal static extern IntPtr CreateFile(
|
|
||||||
[MarshalAs(UnmanagedType.LPWStr)] string filename,
|
|
||||||
[MarshalAs(UnmanagedType.U4)] uint access,
|
|
||||||
[MarshalAs(UnmanagedType.U4)] FileShare share,
|
|
||||||
IntPtr securityAttributes,
|
|
||||||
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
|
|
||||||
[MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
|
|
||||||
IntPtr templateFile);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
|
||||||
internal static extern IntPtr CreatePopupMenu();
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
||||||
internal static extern bool InsertMenu(IntPtr hMenu, uint uPosition, uint uFlags, uint uIDNewItem, string lpNewItem);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
|
||||||
internal static extern bool TrackPopupMenuEx(IntPtr hmenu, uint fuFlags, int x, int y, IntPtr hwnd, IntPtr lptpm);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
||||||
internal static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
||||||
internal static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr hWndChildAfter, string? className, string? windowTitle);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
|
||||||
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
internal static extern bool SetForegroundWindow(IntPtr hWnd);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
||||||
internal static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, nuint wParam, string lParam);
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
|
||||||
internal static extern bool DestroyMenu(IntPtr hMenu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,11 +7,16 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Awake.Core.Models;
|
using Awake.Core.Models;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using Windows.Win32;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.UI.WindowsAndMessaging;
|
||||||
|
|
||||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||||
#pragma warning disable CS8603 // Possible null reference return.
|
#pragma warning disable CS8603 // Possible null reference return.
|
||||||
@@ -22,21 +27,18 @@ namespace Awake.Core
|
|||||||
{
|
{
|
||||||
private static readonly Logger _log;
|
private static readonly Logger _log;
|
||||||
|
|
||||||
private static IntPtr _trayMenu;
|
private static DestroyMenuSafeHandle TrayMenu { get; set; }
|
||||||
|
|
||||||
private static IntPtr TrayMenu { get => _trayMenu; set => _trayMenu = value; }
|
private static NotifyIcon TrayIcon { get; set; }
|
||||||
|
|
||||||
private static NotifyIcon? _trayIcon;
|
|
||||||
|
|
||||||
private static NotifyIcon TrayIcon { get => _trayIcon; set => _trayIcon = value; }
|
|
||||||
|
|
||||||
static TrayHelper()
|
static TrayHelper()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
TrayMenu = new DestroyMenuSafeHandle();
|
||||||
TrayIcon = new NotifyIcon();
|
TrayIcon = new NotifyIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InitializeTray(string text, Icon icon, ContextMenuStrip? contextMenu = null)
|
public static void InitializeTray(string text, Icon icon, ManualResetEvent? exitSignal, ContextMenuStrip? contextMenu = null)
|
||||||
{
|
{
|
||||||
Task.Factory.StartNew(
|
Task.Factory.StartNew(
|
||||||
(tray) =>
|
(tray) =>
|
||||||
@@ -49,7 +51,7 @@ namespace Awake.Core
|
|||||||
((NotifyIcon?)tray).ContextMenuStrip = contextMenu;
|
((NotifyIcon?)tray).ContextMenuStrip = contextMenu;
|
||||||
((NotifyIcon?)tray).Visible = true;
|
((NotifyIcon?)tray).Visible = true;
|
||||||
((NotifyIcon?)tray).MouseClick += TrayClickHandler;
|
((NotifyIcon?)tray).MouseClick += TrayClickHandler;
|
||||||
Application.AddMessageFilter(new TrayMessageFilter());
|
Application.AddMessageFilter(new TrayMessageFilter(exitSignal));
|
||||||
Application.Run();
|
Application.Run();
|
||||||
_log.Info("Tray setup complete.");
|
_log.Info("Tray setup complete.");
|
||||||
}
|
}
|
||||||
@@ -74,21 +76,15 @@ namespace Awake.Core
|
|||||||
/// <param name="e">MouseEventArgs instance containing mouse click event information.</param>
|
/// <param name="e">MouseEventArgs instance containing mouse click event information.</param>
|
||||||
private static void TrayClickHandler(object? sender, MouseEventArgs e)
|
private static void TrayClickHandler(object? sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
IntPtr windowHandle = APIHelper.GetHiddenWindow();
|
HWND windowHandle = APIHelper.GetHiddenWindow();
|
||||||
|
|
||||||
if (windowHandle != IntPtr.Zero)
|
if (windowHandle != HWND.Null)
|
||||||
{
|
{
|
||||||
NativeMethods.SetForegroundWindow(windowHandle);
|
PInvoke.SetForegroundWindow(windowHandle);
|
||||||
NativeMethods.TrackPopupMenuEx(TrayMenu, 0, Cursor.Position.X, Cursor.Position.Y, windowHandle, IntPtr.Zero);
|
PInvoke.TrackPopupMenuEx(TrayMenu, 0, Cursor.Position.X, Cursor.Position.Y, windowHandle, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ClearTray()
|
|
||||||
{
|
|
||||||
TrayIcon.Icon = null;
|
|
||||||
TrayIcon.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void SetTray(string text, AwakeSettings settings)
|
internal static void SetTray(string text, AwakeSettings settings)
|
||||||
{
|
{
|
||||||
SetTray(
|
SetTray(
|
||||||
@@ -101,19 +97,14 @@ namespace Awake.Core
|
|||||||
[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:Single line comments should begin with single space", Justification = "For debugging purposes - will remove later.")]
|
[SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:Single line comments should begin with single space", Justification = "For debugging purposes - will remove later.")]
|
||||||
public static void SetTray(string text, bool keepDisplayOn, AwakeMode mode, Dictionary<string, int> trayTimeShortcuts)
|
public static void SetTray(string text, bool keepDisplayOn, AwakeMode mode, Dictionary<string, int> trayTimeShortcuts)
|
||||||
{
|
{
|
||||||
if (TrayMenu != IntPtr.Zero)
|
TrayMenu = new DestroyMenuSafeHandle(PInvoke.CreatePopupMenu());
|
||||||
{
|
|
||||||
var destructionStatus = NativeMethods.DestroyMenu(TrayMenu);
|
|
||||||
if (destructionStatus != true)
|
|
||||||
{
|
|
||||||
_log.Error("Failed to destroy tray menu and free up memory.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TrayMenu = NativeMethods.CreatePopupMenu();
|
if (!TrayMenu.IsInvalid)
|
||||||
NativeMethods.InsertMenu(TrayMenu, 0, NativeConstants.MF_BYPOSITION | NativeConstants.MF_STRING, (uint)TrayCommands.TC_EXIT, "Exit");
|
{
|
||||||
NativeMethods.InsertMenu(TrayMenu, 0, NativeConstants.MF_BYPOSITION | NativeConstants.MF_SEPARATOR, 0, string.Empty);
|
PInvoke.InsertMenu(TrayMenu, 0, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_STRING, (uint)TrayCommands.TC_EXIT, "Exit");
|
||||||
NativeMethods.InsertMenu(TrayMenu, 0, NativeConstants.MF_BYPOSITION | NativeConstants.MF_STRING | (keepDisplayOn ? NativeConstants.MF_CHECKED : NativeConstants.MF_UNCHECKED), (uint)TrayCommands.TC_DISPLAY_SETTING, "Keep screen on");
|
PInvoke.InsertMenu(TrayMenu, 0, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_SEPARATOR, 0, string.Empty);
|
||||||
|
PInvoke.InsertMenu(TrayMenu, 0, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_STRING | (keepDisplayOn ? MENU_ITEM_FLAGS.MF_CHECKED : MENU_ITEM_FLAGS.MF_UNCHECKED), (uint)TrayCommands.TC_DISPLAY_SETTING, "Keep screen on");
|
||||||
|
}
|
||||||
|
|
||||||
// In case there are no tray shortcuts defined for the application default to a
|
// In case there are no tray shortcuts defined for the application default to a
|
||||||
// reasonable initial set.
|
// reasonable initial set.
|
||||||
@@ -123,18 +114,18 @@ namespace Awake.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make sure that this loads from JSON instead of being hard-coded.
|
// TODO: Make sure that this loads from JSON instead of being hard-coded.
|
||||||
var awakeTimeMenu = NativeMethods.CreatePopupMenu();
|
var awakeTimeMenu = new DestroyMenuSafeHandle(PInvoke.CreatePopupMenu(), false);
|
||||||
for (int i = 0; i < trayTimeShortcuts.Count; i++)
|
for (int i = 0; i < trayTimeShortcuts.Count; i++)
|
||||||
{
|
{
|
||||||
NativeMethods.InsertMenu(awakeTimeMenu, (uint)i, NativeConstants.MF_BYPOSITION | NativeConstants.MF_STRING, (uint)TrayCommands.TC_TIME + (uint)i, trayTimeShortcuts.ElementAt(i).Key);
|
PInvoke.InsertMenu(awakeTimeMenu, (uint)i, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_STRING, (uint)TrayCommands.TC_TIME + (uint)i, trayTimeShortcuts.ElementAt(i).Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
var modeMenu = NativeMethods.CreatePopupMenu();
|
var modeMenu = new DestroyMenuSafeHandle(PInvoke.CreatePopupMenu(), false);
|
||||||
NativeMethods.InsertMenu(modeMenu, 0, NativeConstants.MF_BYPOSITION | NativeConstants.MF_STRING | (mode == AwakeMode.PASSIVE ? NativeConstants.MF_CHECKED : NativeConstants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_PASSIVE, "Off (keep using the selected power plan)");
|
PInvoke.InsertMenu(modeMenu, 0, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_STRING | (mode == AwakeMode.PASSIVE ? MENU_ITEM_FLAGS.MF_CHECKED : MENU_ITEM_FLAGS.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_PASSIVE, "Off (keep using the selected power plan)");
|
||||||
NativeMethods.InsertMenu(modeMenu, 1, NativeConstants.MF_BYPOSITION | NativeConstants.MF_STRING | (mode == AwakeMode.INDEFINITE ? NativeConstants.MF_CHECKED : NativeConstants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_INDEFINITE, "Keep awake indefinitely");
|
PInvoke.InsertMenu(modeMenu, 1, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_STRING | (mode == AwakeMode.INDEFINITE ? MENU_ITEM_FLAGS.MF_CHECKED : MENU_ITEM_FLAGS.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_INDEFINITE, "Keep awake indefinitely");
|
||||||
|
|
||||||
NativeMethods.InsertMenu(modeMenu, 2, NativeConstants.MF_BYPOSITION | NativeConstants.MF_POPUP | (mode == AwakeMode.TIMED ? NativeConstants.MF_CHECKED : NativeConstants.MF_UNCHECKED), (uint)awakeTimeMenu, "Keep awake temporarily");
|
PInvoke.InsertMenu(modeMenu, 2, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_POPUP | (mode == AwakeMode.TIMED ? MENU_ITEM_FLAGS.MF_CHECKED : MENU_ITEM_FLAGS.MF_UNCHECKED), (uint)awakeTimeMenu.DangerousGetHandle(), "Keep awake temporarily");
|
||||||
NativeMethods.InsertMenu(TrayMenu, 0, NativeConstants.MF_BYPOSITION | NativeConstants.MF_POPUP, (uint)modeMenu, "Mode");
|
PInvoke.InsertMenu(TrayMenu, 0, MENU_ITEM_FLAGS.MF_BYPOSITION | MENU_ITEM_FLAGS.MF_POPUP, (uint)modeMenu.DangerousGetHandle(), "Mode");
|
||||||
|
|
||||||
TrayIcon.Text = text;
|
TrayIcon.Text = text;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Awake.Core.Models;
|
using Awake.Core.Models;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
|
using Windows.Win32;
|
||||||
|
|
||||||
#pragma warning disable CS8603 // Possible null reference return.
|
#pragma warning disable CS8603 // Possible null reference return.
|
||||||
|
|
||||||
@@ -20,8 +22,11 @@ namespace Awake.Core
|
|||||||
|
|
||||||
private static SettingsUtils ModuleSettings { get => _moduleSettings; set => _moduleSettings = value; }
|
private static SettingsUtils ModuleSettings { get => _moduleSettings; set => _moduleSettings = value; }
|
||||||
|
|
||||||
public TrayMessageFilter()
|
private static ManualResetEvent? _exitSignal;
|
||||||
|
|
||||||
|
public TrayMessageFilter(ManualResetEvent? exitSignal)
|
||||||
{
|
{
|
||||||
|
_exitSignal = exitSignal;
|
||||||
ModuleSettings = new SettingsUtils();
|
ModuleSettings = new SettingsUtils();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,12 +36,12 @@ namespace Awake.Core
|
|||||||
|
|
||||||
switch (m.Msg)
|
switch (m.Msg)
|
||||||
{
|
{
|
||||||
case (int)NativeConstants.WM_COMMAND:
|
case (int)PInvoke.WM_COMMAND:
|
||||||
var targetCommandIndex = m.WParam.ToInt64() & 0xFFFF;
|
var targetCommandIndex = m.WParam.ToInt64() & 0xFFFF;
|
||||||
switch (targetCommandIndex)
|
switch (targetCommandIndex)
|
||||||
{
|
{
|
||||||
case (long)TrayCommands.TC_EXIT:
|
case (long)TrayCommands.TC_EXIT:
|
||||||
ExitCommandHandler();
|
ExitCommandHandler(_exitSignal);
|
||||||
break;
|
break;
|
||||||
case (long)TrayCommands.TC_DISPLAY_SETTING:
|
case (long)TrayCommands.TC_DISPLAY_SETTING:
|
||||||
DisplaySettingCommandHandler(InternalConstants.AppName);
|
DisplaySettingCommandHandler(InternalConstants.AppName);
|
||||||
@@ -68,9 +73,9 @@ namespace Awake.Core
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ExitCommandHandler()
|
private static void ExitCommandHandler(ManualResetEvent? exitSignal)
|
||||||
{
|
{
|
||||||
APIHelper.CompleteExit(0, true);
|
APIHelper.CompleteExit(0, exitSignal, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DisplaySettingCommandHandler(string moduleName)
|
private static void DisplaySettingCommandHandler(string moduleName)
|
||||||
|
|||||||
23
src/modules/awake/Awake/NativeMethods.txt
Normal file
23
src/modules/awake/Awake/NativeMethods.txt
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
AllocConsole
|
||||||
|
CreateFile
|
||||||
|
CreatePopupMenu
|
||||||
|
DestroyMenu
|
||||||
|
DestroyWindow
|
||||||
|
FindWindowEx
|
||||||
|
GetClassName
|
||||||
|
GetCurrentThreadId
|
||||||
|
GetPwrCapabilities
|
||||||
|
GetWindowThreadProcessId
|
||||||
|
HMENU
|
||||||
|
InsertMenu
|
||||||
|
PostQuitMessage
|
||||||
|
SendMessage
|
||||||
|
SetConsoleCtrlHandler
|
||||||
|
SetForegroundWindow
|
||||||
|
SetStdHandle
|
||||||
|
SetThreadExecutionState
|
||||||
|
TrackPopupMenuEx
|
||||||
|
WM_CLOSE
|
||||||
|
WM_COMMAND
|
||||||
|
WM_GETTEXT
|
||||||
|
WM_USER
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.CommandLine;
|
using System.CommandLine;
|
||||||
using System.CommandLine.Invocation;
|
using System.CommandLine.Invocation;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -17,11 +16,15 @@ using System.Text.Json;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Awake.Core;
|
using Awake.Core;
|
||||||
using Awake.Core.Models;
|
|
||||||
using interop;
|
using interop;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
|
using Microsoft.PowerToys.Telemetry.Events;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using Windows.Win32;
|
||||||
|
using Windows.Win32.Foundation;
|
||||||
|
using Windows.Win32.System.Console;
|
||||||
|
using Windows.Win32.System.Power;
|
||||||
|
|
||||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||||
#pragma warning disable CS8603 // Possible null reference return.
|
#pragma warning disable CS8603 // Possible null reference return.
|
||||||
@@ -47,8 +50,8 @@ namespace Awake
|
|||||||
private static Logger? _log;
|
private static Logger? _log;
|
||||||
|
|
||||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
private static ConsoleEventHandler _handler;
|
private static PHANDLER_ROUTINE _handler;
|
||||||
private static SystemPowerCapabilities _powerCapabilities;
|
private static SYSTEM_POWER_CAPABILITIES _powerCapabilities;
|
||||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
|
||||||
private static ManualResetEvent _exitSignal = new ManualResetEvent(false);
|
private static ManualResetEvent _exitSignal = new ManualResetEvent(false);
|
||||||
@@ -63,7 +66,7 @@ namespace Awake
|
|||||||
|
|
||||||
if (!instantiated)
|
if (!instantiated)
|
||||||
{
|
{
|
||||||
Exit(InternalConstants.AppName + " is already running! Exiting the application.", 1, true);
|
Exit(InternalConstants.AppName + " is already running! Exiting the application.", 1, _exitSignal, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_settingsUtils = new SettingsUtils();
|
_settingsUtils = new SettingsUtils();
|
||||||
@@ -82,12 +85,12 @@ namespace Awake
|
|||||||
|
|
||||||
// To make it easier to diagnose future issues, let's get the
|
// To make it easier to diagnose future issues, let's get the
|
||||||
// system power capabilities and aggregate them in the log.
|
// system power capabilities and aggregate them in the log.
|
||||||
NativeMethods.GetPwrCapabilities(out _powerCapabilities);
|
PInvoke.GetPwrCapabilities(out _powerCapabilities);
|
||||||
_log.Info(JsonSerializer.Serialize(_powerCapabilities));
|
_log.Info(JsonSerializer.Serialize(_powerCapabilities));
|
||||||
|
|
||||||
_log.Info("Parsing parameters...");
|
_log.Info("Parsing parameters...");
|
||||||
|
|
||||||
Option<bool>? configOption = new (
|
var configOption = new Option<bool>(
|
||||||
aliases: new[] { "--use-pt-config", "-c" },
|
aliases: new[] { "--use-pt-config", "-c" },
|
||||||
getDefaultValue: () => false,
|
getDefaultValue: () => false,
|
||||||
description: $"Specifies whether {InternalConstants.AppName} will be using the PowerToys configuration file for managing the state.")
|
description: $"Specifies whether {InternalConstants.AppName} will be using the PowerToys configuration file for managing the state.")
|
||||||
@@ -100,7 +103,7 @@ namespace Awake
|
|||||||
|
|
||||||
configOption.Required = false;
|
configOption.Required = false;
|
||||||
|
|
||||||
Option<bool>? displayOption = new (
|
var displayOption = new Option<bool>(
|
||||||
aliases: new[] { "--display-on", "-d" },
|
aliases: new[] { "--display-on", "-d" },
|
||||||
getDefaultValue: () => true,
|
getDefaultValue: () => true,
|
||||||
description: "Determines whether the display should be kept awake.")
|
description: "Determines whether the display should be kept awake.")
|
||||||
@@ -113,7 +116,7 @@ namespace Awake
|
|||||||
|
|
||||||
displayOption.Required = false;
|
displayOption.Required = false;
|
||||||
|
|
||||||
Option<uint>? timeOption = new (
|
var timeOption = new Option<uint>(
|
||||||
aliases: new[] { "--time-limit", "-t" },
|
aliases: new[] { "--time-limit", "-t" },
|
||||||
getDefaultValue: () => 0,
|
getDefaultValue: () => 0,
|
||||||
description: "Determines the interval, in seconds, during which the computer is kept awake.")
|
description: "Determines the interval, in seconds, during which the computer is kept awake.")
|
||||||
@@ -126,7 +129,7 @@ namespace Awake
|
|||||||
|
|
||||||
timeOption.Required = false;
|
timeOption.Required = false;
|
||||||
|
|
||||||
Option<int>? pidOption = new (
|
var pidOption = new Option<int>(
|
||||||
aliases: new[] { "--pid", "-p" },
|
aliases: new[] { "--pid", "-p" },
|
||||||
getDefaultValue: () => 0,
|
getDefaultValue: () => 0,
|
||||||
description: $"Bind the execution of {InternalConstants.AppName} to another process.")
|
description: $"Bind the execution of {InternalConstants.AppName} to another process.")
|
||||||
@@ -156,23 +159,23 @@ namespace Awake
|
|||||||
return rootCommand.InvokeAsync(args).Result;
|
return rootCommand.InvokeAsync(args).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ExitHandler(ControlType ctrlType)
|
private static BOOL ExitHandler(uint ctrlType)
|
||||||
{
|
{
|
||||||
_log.Info($"Exited through handler with control type: {ctrlType}");
|
_log.Info($"Exited through handler with control type: {ctrlType}");
|
||||||
Exit("Exiting from the internal termination handler.", Environment.ExitCode);
|
Exit("Exiting from the internal termination handler.", Environment.ExitCode, _exitSignal);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Exit(string message, int exitCode, bool force = false)
|
private static void Exit(string message, int exitCode, ManualResetEvent exitSignal, bool force = false)
|
||||||
{
|
{
|
||||||
_log.Info(message);
|
_log.Info(message);
|
||||||
|
|
||||||
APIHelper.CompleteExit(exitCode, force);
|
APIHelper.CompleteExit(exitCode, exitSignal, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandleCommandLineArguments(bool usePtConfig, bool displayOn, uint timeLimit, int pid)
|
private static void HandleCommandLineArguments(bool usePtConfig, bool displayOn, uint timeLimit, int pid)
|
||||||
{
|
{
|
||||||
_handler += new ConsoleEventHandler(ExitHandler);
|
_handler += ExitHandler;
|
||||||
APIHelper.SetConsoleControlHandler(_handler, true);
|
APIHelper.SetConsoleControlHandler(_handler, true);
|
||||||
|
|
||||||
if (pid == 0)
|
if (pid == 0)
|
||||||
@@ -192,16 +195,15 @@ namespace Awake
|
|||||||
// and instead watch for changes in the file.
|
// and instead watch for changes in the file.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset, Constants.AwakeExitEvent());
|
||||||
new Thread(() =>
|
new Thread(() =>
|
||||||
{
|
{
|
||||||
EventWaitHandle? eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.AwakeExitEvent());
|
if (WaitHandle.WaitAny(new WaitHandle[] { _exitSignal, eventHandle }) == 1)
|
||||||
if (eventHandle.WaitOne())
|
|
||||||
{
|
{
|
||||||
Exit("Received a signal to end the process. Making sure we quit...", 0, true);
|
Exit("Received a signal to end the process. Making sure we quit...", 0, _exitSignal, true);
|
||||||
}
|
}
|
||||||
}).Start();
|
}).Start();
|
||||||
|
TrayHelper.InitializeTray(InternalConstants.FullAppName, new Icon("modules/awake/images/awake.ico"), _exitSignal);
|
||||||
TrayHelper.InitializeTray(InternalConstants.FullAppName, new Icon("modules/awake/images/awake.ico"));
|
|
||||||
|
|
||||||
string? settingsPath = _settingsUtils.GetSettingsFilePath(InternalConstants.AppName);
|
string? settingsPath = _settingsUtils.GetSettingsFilePath(InternalConstants.AppName);
|
||||||
_log.Info($"Reading configuration file: {settingsPath}");
|
_log.Info($"Reading configuration file: {settingsPath}");
|
||||||
@@ -263,7 +265,7 @@ namespace Awake
|
|||||||
RunnerHelper.WaitForPowerToysRunner(pid, () =>
|
RunnerHelper.WaitForPowerToysRunner(pid, () =>
|
||||||
{
|
{
|
||||||
_log.Info($"Triggered PID-based exit handler for PID {pid}.");
|
_log.Info($"Triggered PID-based exit handler for PID {pid}.");
|
||||||
Exit("Terminating from process binding hook.", 0, true);
|
Exit("Terminating from process binding hook.", 0, _exitSignal, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel.Composition;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using ColorPicker.Helpers;
|
using ColorPicker.Helpers;
|
||||||
@@ -23,8 +24,16 @@ namespace ColorPickerUI
|
|||||||
private bool disposedValue;
|
private bool disposedValue;
|
||||||
private ThemeManager _themeManager;
|
private ThemeManager _themeManager;
|
||||||
|
|
||||||
|
private CancellationTokenSource NativeThreadCTS { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
private static CancellationToken ExitToken { get; set; }
|
||||||
|
|
||||||
protected override void OnStartup(StartupEventArgs e)
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
{
|
{
|
||||||
|
NativeThreadCTS = new CancellationTokenSource();
|
||||||
|
ExitToken = NativeThreadCTS.Token;
|
||||||
|
|
||||||
_args = e?.Args;
|
_args = e?.Args;
|
||||||
|
|
||||||
// allow only one instance of color picker
|
// allow only one instance of color picker
|
||||||
@@ -33,7 +42,7 @@ namespace ColorPickerUI
|
|||||||
{
|
{
|
||||||
Logger.LogWarning("There is ColorPicker instance running. Exiting Color Picker");
|
Logger.LogWarning("There is ColorPicker instance running. Exiting Color Picker");
|
||||||
_instanceMutex = null;
|
_instanceMutex = null;
|
||||||
Environment.Exit(0);
|
Shutdown(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +54,8 @@ namespace ColorPickerUI
|
|||||||
RunnerHelper.WaitForPowerToysRunner(_powerToysRunnerPid, () =>
|
RunnerHelper.WaitForPowerToysRunner(_powerToysRunnerPid, () =>
|
||||||
{
|
{
|
||||||
Logger.LogInfo("PowerToys Runner exited. Exiting ColorPicker");
|
Logger.LogInfo("PowerToys Runner exited. Exiting ColorPicker");
|
||||||
Environment.Exit(0);
|
NativeThreadCTS.Cancel();
|
||||||
|
Dispatcher.Invoke(Shutdown);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ using System.Globalization;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Automation.Peers;
|
using System.Windows.Automation.Peers;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Animation;
|
using System.Windows.Media.Animation;
|
||||||
using ColorPicker.Helpers;
|
using ColorPicker.Helpers;
|
||||||
|
|||||||
@@ -3,11 +3,7 @@
|
|||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Animation;
|
|
||||||
|
|
||||||
namespace ColorPicker.Controls
|
namespace ColorPicker.Controls
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
// 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.Threading;
|
|
||||||
using System.Windows;
|
|
||||||
|
|
||||||
namespace ColorPicker.Helpers
|
|
||||||
{
|
|
||||||
public static class NativeEventWaiter
|
|
||||||
{
|
|
||||||
public static void WaitForEventLoop(string eventName, Action callback)
|
|
||||||
{
|
|
||||||
new Thread(() =>
|
|
||||||
{
|
|
||||||
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (eventHandle.WaitOne())
|
|
||||||
{
|
|
||||||
Logger.LogInfo($"Successfully waited for {eventName}");
|
|
||||||
Application.Current.Dispatcher.Invoke(callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,11 +7,8 @@ using System.ComponentModel.Composition;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using ColorPicker.Telemetry;
|
|
||||||
using ColorPicker.ViewModelContracts;
|
using ColorPicker.ViewModelContracts;
|
||||||
using Microsoft.PowerToys.Telemetry;
|
|
||||||
|
|
||||||
namespace ColorPicker.Helpers
|
namespace ColorPicker.Helpers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ using System.ComponentModel.Composition;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using ColorPicker.Helpers;
|
using ColorPicker.Helpers;
|
||||||
using ColorPicker.Settings;
|
using ColorPicker.Settings;
|
||||||
using ColorPicker.Telemetry;
|
|
||||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
|
||||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||||
using Microsoft.PowerToys.Telemetry;
|
|
||||||
using static ColorPicker.NativeMethods;
|
using static ColorPicker.NativeMethods;
|
||||||
|
|
||||||
namespace ColorPicker.Keyboard
|
namespace ColorPicker.Keyboard
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using ColorPicker.Helpers;
|
using ColorPicker.Helpers;
|
||||||
using ColorPicker.Mouse;
|
using ColorPicker.Mouse;
|
||||||
|
|
||||||
using ColorPickerUI;
|
using ColorPickerUI;
|
||||||
|
|
||||||
namespace ColorPicker
|
namespace ColorPicker
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Diagnostics.Tracing;
|
using System.Diagnostics.Tracing;
|
||||||
using Microsoft.PowerToys.Telemetry;
|
using Microsoft.PowerToys.Telemetry;
|
||||||
using Microsoft.PowerToys.Telemetry.Events;
|
using Microsoft.PowerToys.Telemetry.Events;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
@@ -13,11 +12,9 @@ using ColorPicker.Helpers;
|
|||||||
using ColorPicker.Keyboard;
|
using ColorPicker.Keyboard;
|
||||||
using ColorPicker.Mouse;
|
using ColorPicker.Mouse;
|
||||||
using ColorPicker.Settings;
|
using ColorPicker.Settings;
|
||||||
using ColorPicker.Telemetry;
|
|
||||||
using ColorPicker.ViewModelContracts;
|
using ColorPicker.ViewModelContracts;
|
||||||
|
using Common.UI;
|
||||||
using interop;
|
using interop;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
|
||||||
using Microsoft.PowerToys.Telemetry;
|
|
||||||
|
|
||||||
namespace ColorPicker.ViewModels
|
namespace ColorPicker.ViewModels
|
||||||
{
|
{
|
||||||
@@ -49,13 +46,24 @@ namespace ColorPicker.ViewModels
|
|||||||
ZoomWindowHelper zoomWindowHelper,
|
ZoomWindowHelper zoomWindowHelper,
|
||||||
AppStateHandler appStateHandler,
|
AppStateHandler appStateHandler,
|
||||||
KeyboardMonitor keyboardMonitor,
|
KeyboardMonitor keyboardMonitor,
|
||||||
IUserSettings userSettings)
|
IUserSettings userSettings,
|
||||||
|
CancellationToken exitToken)
|
||||||
{
|
{
|
||||||
_zoomWindowHelper = zoomWindowHelper;
|
_zoomWindowHelper = zoomWindowHelper;
|
||||||
_appStateHandler = appStateHandler;
|
_appStateHandler = appStateHandler;
|
||||||
_userSettings = userSettings;
|
_userSettings = userSettings;
|
||||||
NativeEventWaiter.WaitForEventLoop(Constants.ShowColorPickerSharedEvent(), _appStateHandler.StartUserSession);
|
|
||||||
NativeEventWaiter.WaitForEventLoop(Constants.ColorPickerSendSettingsTelemetryEvent(), _userSettings.SendSettingsTelemetry);
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
|
Constants.ShowColorPickerSharedEvent(),
|
||||||
|
_appStateHandler.StartUserSession,
|
||||||
|
Application.Current.Dispatcher,
|
||||||
|
exitToken);
|
||||||
|
|
||||||
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
|
Constants.ColorPickerSendSettingsTelemetryEvent(),
|
||||||
|
_userSettings.SendSettingsTelemetry,
|
||||||
|
Application.Current.Dispatcher,
|
||||||
|
exitToken);
|
||||||
|
|
||||||
if (mouseInfoProvider != null)
|
if (mouseInfoProvider != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace ColorPicker
|
namespace ColorPicker
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Threading;
|
||||||
using Common.UI;
|
using Common.UI;
|
||||||
using FancyZonesEditor.Logs;
|
using FancyZonesEditor.Logs;
|
||||||
using FancyZonesEditor.Utils;
|
using FancyZonesEditor.Utils;
|
||||||
@@ -35,10 +35,6 @@ namespace FancyZonesEditor
|
|||||||
|
|
||||||
private ThemeManager _themeManager;
|
private ThemeManager _themeManager;
|
||||||
|
|
||||||
private EventWaitHandle _eventHandle;
|
|
||||||
|
|
||||||
private Thread _exitWaitThread;
|
|
||||||
|
|
||||||
public static bool DebugMode
|
public static bool DebugMode
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -50,6 +46,8 @@ namespace FancyZonesEditor
|
|||||||
private static bool _debugMode;
|
private static bool _debugMode;
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
|
|
||||||
|
private CancellationTokenSource NativeThreadCTS { get; set; }
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
[Conditional("DEBUG")]
|
||||||
private void DebugModeCheck()
|
private void DebugModeCheck()
|
||||||
{
|
{
|
||||||
@@ -59,27 +57,29 @@ namespace FancyZonesEditor
|
|||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
// DebugModeCheck();
|
// DebugModeCheck();
|
||||||
|
NativeThreadCTS = new CancellationTokenSource();
|
||||||
FancyZonesEditorIO = new FancyZonesEditorIO();
|
FancyZonesEditorIO = new FancyZonesEditorIO();
|
||||||
Overlay = new Overlay();
|
Overlay = new Overlay();
|
||||||
MainWindowSettings = new MainWindowSettingsModel();
|
MainWindowSettings = new MainWindowSettingsModel();
|
||||||
|
|
||||||
_exitWaitThread = new Thread(App_WaitExit);
|
App_WaitExit();
|
||||||
_exitWaitThread.Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnStartup(object sender, StartupEventArgs e)
|
private void OnStartup(object sender, StartupEventArgs e)
|
||||||
{
|
{
|
||||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||||
|
|
||||||
RunnerHelper.WaitForPowerToysRunner(PowerToysPID, () =>
|
|
||||||
{
|
|
||||||
Logger.LogInfo("Runner exited");
|
|
||||||
Environment.Exit(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
_themeManager = new ThemeManager(this);
|
_themeManager = new ThemeManager(this);
|
||||||
|
|
||||||
var parseResult = FancyZonesEditorIO.ParseParams();
|
var parseResult = FancyZonesEditorIO.ParseParams();
|
||||||
|
|
||||||
|
RunnerHelper.WaitForPowerToysRunner(PowerToysPID, () =>
|
||||||
|
{
|
||||||
|
Logger.LogInfo("Runner exited");
|
||||||
|
NativeThreadCTS.Cancel();
|
||||||
|
Application.Current.Dispatcher.Invoke(Application.Current.Shutdown);
|
||||||
|
});
|
||||||
|
|
||||||
if (!parseResult.Result)
|
if (!parseResult.Result)
|
||||||
{
|
{
|
||||||
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
|
Logger.LogError(ParsingErrorReportTag + ": " + parseResult.Message + "; " + ParsingErrorDataTag + ": " + parseResult.MalformedData);
|
||||||
@@ -122,26 +122,23 @@ namespace FancyZonesEditor
|
|||||||
|
|
||||||
private void OnExit(object sender, ExitEventArgs e)
|
private void OnExit(object sender, ExitEventArgs e)
|
||||||
{
|
{
|
||||||
|
NativeThreadCTS.Cancel();
|
||||||
Dispose();
|
Dispose();
|
||||||
|
|
||||||
if (_eventHandle != null)
|
|
||||||
{
|
|
||||||
_eventHandle.Set();
|
|
||||||
}
|
|
||||||
|
|
||||||
_exitWaitThread.Join();
|
|
||||||
|
|
||||||
Logger.LogInfo("FancyZones Editor exited");
|
Logger.LogInfo("FancyZones Editor exited");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void App_WaitExit()
|
private void App_WaitExit()
|
||||||
{
|
{
|
||||||
_eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, interop.Constants.FZEExitEvent());
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
if (_eventHandle.WaitOne())
|
interop.Constants.FZEExitEvent(),
|
||||||
|
() =>
|
||||||
{
|
{
|
||||||
Logger.LogInfo("Exit event triggered");
|
Logger.LogInfo("Exit event triggered");
|
||||||
Environment.Exit(0);
|
Application.Current.Shutdown();
|
||||||
}
|
},
|
||||||
|
Current.Dispatcher,
|
||||||
|
NativeThreadCTS.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void App_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
|
public void App_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
|
||||||
|
|||||||
@@ -72,13 +72,16 @@ namespace PowerLauncher
|
|||||||
using (var application = new App())
|
using (var application = new App())
|
||||||
{
|
{
|
||||||
application.InitializeComponent();
|
application.InitializeComponent();
|
||||||
|
|
||||||
NativeEventWaiter.WaitForEventLoop(
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
Constants.RunExitEvent(),
|
Constants.RunExitEvent(),
|
||||||
() =>
|
() =>
|
||||||
{
|
{
|
||||||
Log.Warn("RunExitEvent was signaled. Exiting PowerToys", typeof(App));
|
Log.Warn("RunExitEvent was signaled. Exiting PowerToys", typeof(App));
|
||||||
ExitPowerToys(application);
|
ExitPowerToys(application);
|
||||||
}, NativeThreadCTS.Token);
|
},
|
||||||
|
Application.Current.Dispatcher,
|
||||||
|
NativeThreadCTS.Token);
|
||||||
|
|
||||||
if (powerToysPid != 0)
|
if (powerToysPid != 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using System.Windows;
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
|
using Common.UI;
|
||||||
using interop;
|
using interop;
|
||||||
using Microsoft.PowerLauncher.Telemetry;
|
using Microsoft.PowerLauncher.Telemetry;
|
||||||
using Microsoft.PowerToys.Telemetry;
|
using Microsoft.PowerToys.Telemetry;
|
||||||
@@ -52,7 +53,11 @@ namespace PowerLauncher
|
|||||||
|
|
||||||
_firstDeleteTimer.Elapsed += CheckForFirstDelete;
|
_firstDeleteTimer.Elapsed += CheckForFirstDelete;
|
||||||
_firstDeleteTimer.Interval = 1000;
|
_firstDeleteTimer.Interval = 1000;
|
||||||
NativeEventWaiter.WaitForEventLoop(Constants.RunSendSettingsTelemetryEvent(), SendSettingsTelemetry, _nativeWaiterCancelToken);
|
NativeEventWaiter.WaitForEventLoop(
|
||||||
|
Constants.RunSendSettingsTelemetryEvent(),
|
||||||
|
SendSettingsTelemetry,
|
||||||
|
Application.Current.Dispatcher,
|
||||||
|
_nativeWaiterCancelToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendSettingsTelemetry()
|
private void SendSettingsTelemetry()
|
||||||
@@ -701,7 +706,15 @@ namespace PowerLauncher
|
|||||||
|
|
||||||
private void OnClosed(object sender, EventArgs e)
|
private void OnClosed(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
_hwndSource.RemoveHook(ProcessWindowMessages);
|
try
|
||||||
|
{
|
||||||
|
_hwndSource.RemoveHook(ProcessWindowMessages);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Exception($"Exception when trying to Remove hook", ex, ex.GetType());
|
||||||
|
}
|
||||||
|
|
||||||
_hwndSource = null;
|
_hwndSource = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,19 +49,6 @@ namespace Wox
|
|||||||
_mainVM.ChangeQueryText(query, requery);
|
_mainVM.ChangeQueryText(query, requery);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RestartApp()
|
|
||||||
{
|
|
||||||
_mainVM.MainWindowVisibility = Visibility.Hidden;
|
|
||||||
|
|
||||||
// we must manually save
|
|
||||||
// UpdateManager.RestartApp() will call Environment.Exit(0)
|
|
||||||
// which will cause ungraceful exit
|
|
||||||
SaveAppAllSettings();
|
|
||||||
|
|
||||||
// Todo : Implement logic to restart this app.
|
|
||||||
Environment.Exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CheckForNewUpdate()
|
public void CheckForNewUpdate()
|
||||||
{
|
{
|
||||||
// _settingsVM.UpdateApp();
|
// _settingsVM.UpdateApp();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using System.Threading.Tasks;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
using Common.UI;
|
||||||
using interop;
|
using interop;
|
||||||
using Microsoft.PowerLauncher.Telemetry;
|
using Microsoft.PowerLauncher.Telemetry;
|
||||||
using Microsoft.PowerToys.Telemetry;
|
using Microsoft.PowerToys.Telemetry;
|
||||||
@@ -93,12 +94,12 @@ namespace PowerLauncher.ViewModel
|
|||||||
Log.Info("RegisterHotkey()", GetType());
|
Log.Info("RegisterHotkey()", GetType());
|
||||||
|
|
||||||
// Allow OOBE to call PowerToys Run.
|
// Allow OOBE to call PowerToys Run.
|
||||||
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherSharedEvent(), OnHotkey, _nativeWaiterCancelToken);
|
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherSharedEvent(), OnHotkey, Application.Current.Dispatcher, _nativeWaiterCancelToken);
|
||||||
|
|
||||||
if (_settings.StartedFromPowerToysRunner)
|
if (_settings.StartedFromPowerToysRunner)
|
||||||
{
|
{
|
||||||
// Allow runner to call PowerToys Run from the centralized keyboard hook.
|
// Allow runner to call PowerToys Run from the centralized keyboard hook.
|
||||||
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherCentralizedHookSharedEvent(), OnCentralizedKeyboardHookHotKey, _nativeWaiterCancelToken);
|
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherCentralizedHookSharedEvent(), OnCentralizedKeyboardHookHotKey, Application.Current.Dispatcher, _nativeWaiterCancelToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
_settings.PropertyChanged += (s, e) =>
|
_settings.PropertyChanged += (s, e) =>
|
||||||
|
|||||||
@@ -23,11 +23,6 @@ namespace Wox.Plugin
|
|||||||
/// </param>
|
/// </param>
|
||||||
void ChangeQuery(string query, bool requery = false);
|
void ChangeQuery(string query, bool requery = false);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Restart Wox
|
|
||||||
/// </summary>
|
|
||||||
void RestartApp();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remove user selected history item and refresh/requery
|
/// Remove user selected history item and refresh/requery
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user