mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 03:37:59 +01:00
[Awake]PROMETHEAN_09082024 - tray icon fixes (#34717)
* Update with bug fixes for tray icon and support for parent process * Process information enum * Update the docs * Fix spelling * Make sure that PID is used in PT config flow * Logic for checks based on #34148 * Update with link to PR * Small cleanup * Proper task segmentation in a function * Cleanup the code * Fix synchronization context issue * Update planning doc * Test disabling caching to see if that manages to pass CI
This commit is contained in:
@@ -32,7 +32,7 @@ parameters:
|
|||||||
- name: enableMsBuildCaching
|
- name: enableMsBuildCaching
|
||||||
type: boolean
|
type: boolean
|
||||||
displayName: "Enable MSBuild Caching"
|
displayName: "Enable MSBuild Caching"
|
||||||
default: true
|
default: false
|
||||||
- name: runTests
|
- name: runTests
|
||||||
type: boolean
|
type: boolean
|
||||||
displayName: "Run Tests"
|
displayName: "Run Tests"
|
||||||
|
|||||||
@@ -11,13 +11,22 @@ The build ID can be found in `Core\Constants.cs` in the `BuildId` variable - it
|
|||||||
The build ID moniker is made up of two components - a reference to a [Halo](https://en.wikipedia.org/wiki/Halo_(franchise)) character, and the date when the work on the specific build started in the format of `MMDDYYYY`.
|
The build ID moniker is made up of two components - a reference to a [Halo](https://en.wikipedia.org/wiki/Halo_(franchise)) character, and the date when the work on the specific build started in the format of `MMDDYYYY`.
|
||||||
|
|
||||||
| Build ID | Build Date |
|
| Build ID | Build Date |
|
||||||
|:-------------------------------------------------------------------|:----------------|
|
|:-------------------------------------------------------------------|:------------------|
|
||||||
|
| [`PROMETHEAN_09082024`](#PROMETHEAN_09082024-september-8-2024) | September 8, 2024 |
|
||||||
| [`VISEGRADRELAY_08152024`](#VISEGRADRELAY_08152024-august-15-2024) | August 15, 2024 |
|
| [`VISEGRADRELAY_08152024`](#VISEGRADRELAY_08152024-august-15-2024) | August 15, 2024 |
|
||||||
| [`DAISY023_04102024`](#DAISY023_04102024-april-10-2024) | April 10, 2024 |
|
| [`DAISY023_04102024`](#DAISY023_04102024-april-10-2024) | April 10, 2024 |
|
||||||
| [`ATRIOX_04132023`](#ATRIOX_04132023-april-13-2023) | April 13, 2023 |
|
| [`ATRIOX_04132023`](#ATRIOX_04132023-april-13-2023) | April 13, 2023 |
|
||||||
| [`LIBRARIAN_03202022`](#librarian_03202022-march-20-2022) | March 20, 2022 |
|
| [`LIBRARIAN_03202022`](#librarian_03202022-march-20-2022) | March 20, 2022 |
|
||||||
| `ARBITER_01312022` | January 31, 2022 |
|
| `ARBITER_01312022` | January 31, 2022 |
|
||||||
|
|
||||||
|
### `PROMETHEAN_09082024` (September 8, 2024)
|
||||||
|
|
||||||
|
>[!NOTE]
|
||||||
|
>See pull request: [Awake - `PROMETHEAN_09082024`](https://github.com/microsoft/PowerToys/pull/34717)
|
||||||
|
|
||||||
|
- Updating the initialization logic to make sure that settings are respected for proper group policy and single-instance detection.
|
||||||
|
- [#34148] Fixed a bug from the previous release that incorrectly synchronized threads for shell icon creation and initialized parent PID when it was not parented.
|
||||||
|
|
||||||
### `VISEGRADRELAY_08152024` (August 15, 2024)
|
### `VISEGRADRELAY_08152024` (August 15, 2024)
|
||||||
|
|
||||||
>[!NOTE]
|
>[!NOTE]
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ namespace Awake.Core
|
|||||||
// Format of the build ID is: CODENAME_MMDDYYYY, where MMDDYYYY
|
// Format of the build ID is: CODENAME_MMDDYYYY, where MMDDYYYY
|
||||||
// is representative of the date when the last change was made before
|
// is representative of the date when the last change was made before
|
||||||
// the pull request is issued.
|
// the pull request is issued.
|
||||||
internal const string BuildId = "VISEGRADRELAY_08152024";
|
internal const string BuildId = "PROMETHEAN_09082024";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,16 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Awake.Core.Models
|
namespace Awake.Core.Threading
|
||||||
{
|
{
|
||||||
internal sealed class SingleThreadSynchronizationContext : SynchronizationContext
|
internal sealed class SingleThreadSynchronizationContext : SynchronizationContext
|
||||||
{
|
{
|
||||||
private readonly Queue<Tuple<SendOrPostCallback, object>> queue =
|
private readonly Queue<Tuple<SendOrPostCallback, object?>?> queue = new();
|
||||||
new();
|
|
||||||
|
|
||||||
#pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
|
public override void Post(SendOrPostCallback d, object? state)
|
||||||
public override void Post(SendOrPostCallback d, object state)
|
|
||||||
#pragma warning restore CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes).
|
|
||||||
{
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(d);
|
||||||
|
|
||||||
lock (queue)
|
lock (queue)
|
||||||
{
|
{
|
||||||
queue.Enqueue(Tuple.Create(d, state));
|
queue.Enqueue(Tuple.Create(d, state));
|
||||||
@@ -28,7 +27,7 @@ namespace Awake.Core.Models
|
|||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Tuple<SendOrPostCallback, object> work;
|
Tuple<SendOrPostCallback, object?>? work;
|
||||||
lock (queue)
|
lock (queue)
|
||||||
{
|
{
|
||||||
while (queue.Count == 0)
|
while (queue.Count == 0)
|
||||||
@@ -44,17 +43,22 @@ namespace Awake.Core.Models
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
work.Item1(work.Item2);
|
work.Item1(work.Item2);
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error during execution: " + e.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndMessageLoop()
|
public void EndMessageLoop()
|
||||||
{
|
{
|
||||||
lock (queue)
|
lock (queue)
|
||||||
{
|
{
|
||||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
|
||||||
queue.Enqueue(null); // Signal the end of the message loop
|
queue.Enqueue(null); // Signal the end of the message loop
|
||||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
|
||||||
Monitor.Pulse(queue);
|
Monitor.Pulse(queue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,9 @@ using System.Drawing;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using Awake.Core.Models;
|
using Awake.Core.Models;
|
||||||
using Awake.Core.Native;
|
using Awake.Core.Native;
|
||||||
|
using Awake.Core.Threading;
|
||||||
using Awake.Properties;
|
using Awake.Properties;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
@@ -29,13 +28,13 @@ namespace Awake.Core
|
|||||||
internal static class TrayHelper
|
internal static class TrayHelper
|
||||||
{
|
{
|
||||||
private static NotifyIconData _notifyIconData;
|
private static NotifyIconData _notifyIconData;
|
||||||
|
|
||||||
private static IntPtr _trayMenu;
|
private static IntPtr _trayMenu;
|
||||||
|
private static IntPtr _hiddenWindowHandle;
|
||||||
|
private static SingleThreadSynchronizationContext? _syncContext;
|
||||||
|
private static Thread? _mainThread;
|
||||||
|
|
||||||
private static IntPtr TrayMenu { get => _trayMenu; set => _trayMenu = value; }
|
private static IntPtr TrayMenu { get => _trayMenu; set => _trayMenu = value; }
|
||||||
|
|
||||||
private static IntPtr _hiddenWindowHandle;
|
|
||||||
|
|
||||||
internal static IntPtr HiddenWindowHandle { get => _hiddenWindowHandle; private set => _hiddenWindowHandle = value; }
|
internal static IntPtr HiddenWindowHandle { get => _hiddenWindowHandle; private set => _hiddenWindowHandle = value; }
|
||||||
|
|
||||||
static TrayHelper()
|
static TrayHelper()
|
||||||
@@ -46,51 +45,47 @@ namespace Awake.Core
|
|||||||
|
|
||||||
private static void ShowContextMenu(IntPtr hWnd)
|
private static void ShowContextMenu(IntPtr hWnd)
|
||||||
{
|
{
|
||||||
if (TrayMenu != IntPtr.Zero)
|
if (TrayMenu == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
|
Logger.LogError("Tried to create a context menu while the TrayMenu object is a null pointer. Normal when used in standalone mode.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Bridge.SetForegroundWindow(hWnd);
|
Bridge.SetForegroundWindow(hWnd);
|
||||||
|
|
||||||
// Get the handle to the context menu associated with the tray icon
|
// Get cursor position and convert it to client coordinates
|
||||||
IntPtr hMenu = TrayMenu;
|
|
||||||
|
|
||||||
// Get the current cursor position
|
|
||||||
Bridge.GetCursorPos(out Models.Point cursorPos);
|
Bridge.GetCursorPos(out Models.Point cursorPos);
|
||||||
|
|
||||||
Bridge.ScreenToClient(hWnd, ref cursorPos);
|
Bridge.ScreenToClient(hWnd, ref cursorPos);
|
||||||
|
|
||||||
MenuInfo menuInfo = new()
|
// Set menu information
|
||||||
|
var menuInfo = new MenuInfo
|
||||||
{
|
{
|
||||||
CbSize = (uint)Marshal.SizeOf(typeof(MenuInfo)),
|
CbSize = (uint)Marshal.SizeOf<MenuInfo>(),
|
||||||
FMask = Native.Constants.MIM_STYLE,
|
FMask = Native.Constants.MIM_STYLE,
|
||||||
DwStyle = Native.Constants.MNS_AUTO_DISMISS,
|
DwStyle = Native.Constants.MNS_AUTO_DISMISS,
|
||||||
};
|
};
|
||||||
Bridge.SetMenuInfo(hMenu, ref menuInfo);
|
Bridge.SetMenuInfo(TrayMenu, ref menuInfo);
|
||||||
|
|
||||||
// Display the context menu at the cursor position
|
// Display the context menu at the cursor position
|
||||||
Bridge.TrackPopupMenuEx(
|
Bridge.TrackPopupMenuEx(
|
||||||
hMenu,
|
TrayMenu,
|
||||||
Native.Constants.TPM_LEFT_ALIGN | Native.Constants.TPM_BOTTOMALIGN | Native.Constants.TPM_LEFT_BUTTON,
|
Native.Constants.TPM_LEFT_ALIGN | Native.Constants.TPM_BOTTOMALIGN | Native.Constants.TPM_LEFT_BUTTON,
|
||||||
cursorPos.X,
|
cursorPos.X,
|
||||||
cursorPos.Y,
|
cursorPos.Y,
|
||||||
hWnd,
|
hWnd,
|
||||||
IntPtr.Zero);
|
IntPtr.Zero);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Tray menu was not initialized. Log the issue.
|
|
||||||
// This is normal when operating in "standalone mode" - that is, detached
|
|
||||||
// from the PowerToys configuration file.
|
|
||||||
Logger.LogError("Tried to create a context menu while the TrayMenu object is a null pointer. Normal when used in standalone mode.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void InitializeTray(Icon icon, string text)
|
public static void InitializeTray(Icon icon, string text)
|
||||||
{
|
{
|
||||||
IntPtr hWnd = IntPtr.Zero;
|
IntPtr hWnd = IntPtr.Zero;
|
||||||
|
|
||||||
// Start the message loop asynchronously
|
// Start the message loop asynchronously
|
||||||
Task.Run(() =>
|
_mainThread = new Thread(() =>
|
||||||
{
|
{
|
||||||
|
_syncContext = new SingleThreadSynchronizationContext();
|
||||||
|
SynchronizationContext.SetSynchronizationContext(_syncContext);
|
||||||
|
|
||||||
RunOnMainThread(() =>
|
RunOnMainThread(() =>
|
||||||
{
|
{
|
||||||
WndClassEx wcex = new()
|
WndClassEx wcex = new()
|
||||||
@@ -137,24 +132,27 @@ namespace Awake.Core
|
|||||||
|
|
||||||
Bridge.ShowWindow(hWnd, 0); // SW_HIDE
|
Bridge.ShowWindow(hWnd, 0); // SW_HIDE
|
||||||
Bridge.UpdateWindow(hWnd);
|
Bridge.UpdateWindow(hWnd);
|
||||||
|
Logger.LogInfo($"Created HWND for the window: {hWnd}");
|
||||||
|
|
||||||
SetShellIcon(hWnd, text, icon);
|
SetShellIcon(hWnd, text, icon);
|
||||||
});
|
});
|
||||||
}).Wait();
|
|
||||||
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
|
||||||
RunOnMainThread(() =>
|
RunOnMainThread(() =>
|
||||||
{
|
{
|
||||||
RunMessageLoop();
|
RunMessageLoop();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_syncContext!.BeginMessageLoop();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_mainThread.IsBackground = true;
|
||||||
|
_mainThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetShellIcon(IntPtr hWnd, string text, Icon? icon, TrayIconAction action = TrayIconAction.Add)
|
internal static void SetShellIcon(IntPtr hWnd, string text, Icon? icon, TrayIconAction action = TrayIconAction.Add)
|
||||||
{
|
{
|
||||||
Logger.LogInfo($"Setting the shell icon.\nText: {text}\nAction: {action}");
|
if (hWnd != IntPtr.Zero && icon != null)
|
||||||
|
{
|
||||||
int message = Native.Constants.NIM_ADD;
|
int message = Native.Constants.NIM_ADD;
|
||||||
|
|
||||||
switch (action)
|
switch (action)
|
||||||
@@ -172,8 +170,6 @@ namespace Awake.Core
|
|||||||
|
|
||||||
if (action == TrayIconAction.Add || action == TrayIconAction.Update)
|
if (action == TrayIconAction.Add || action == TrayIconAction.Update)
|
||||||
{
|
{
|
||||||
Logger.LogInfo($"Adding or updating tray icon. HIcon handle is {icon?.Handle}\nHWnd: {hWnd}");
|
|
||||||
|
|
||||||
_notifyIconData = new NotifyIconData
|
_notifyIconData = new NotifyIconData
|
||||||
{
|
{
|
||||||
CbSize = Marshal.SizeOf(typeof(NotifyIconData)),
|
CbSize = Marshal.SizeOf(typeof(NotifyIconData)),
|
||||||
@@ -199,6 +195,8 @@ namespace Awake.Core
|
|||||||
if (!Bridge.Shell_NotifyIcon(message, ref _notifyIconData))
|
if (!Bridge.Shell_NotifyIcon(message, ref _notifyIconData))
|
||||||
{
|
{
|
||||||
int errorCode = Marshal.GetLastWin32Error();
|
int errorCode = Marshal.GetLastWin32Error();
|
||||||
|
Logger.LogInfo($"Could not set the shell icon. Action: {action} and error code: {errorCode}. HIcon handle is {icon?.Handle} and HWnd is {hWnd}");
|
||||||
|
|
||||||
throw new Win32Exception(errorCode, $"Failed to change tray icon. Action: {action} and error code: {errorCode}");
|
throw new Win32Exception(errorCode, $"Failed to change tray icon. Action: {action} and error code: {errorCode}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,6 +205,11 @@ namespace Awake.Core
|
|||||||
_notifyIconData = default;
|
_notifyIconData = default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.LogInfo($"Cannot set the shell icon - parent window handle is zero or icon is not available. Text: {text} Action: {action}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void RunMessageLoop()
|
private static void RunMessageLoop()
|
||||||
{
|
{
|
||||||
@@ -215,6 +218,8 @@ namespace Awake.Core
|
|||||||
Bridge.TranslateMessage(ref msg);
|
Bridge.TranslateMessage(ref msg);
|
||||||
Bridge.DispatchMessage(ref msg);
|
Bridge.DispatchMessage(ref msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.LogInfo("Message loop terminated.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int WndProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam)
|
private static int WndProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam)
|
||||||
@@ -295,30 +300,20 @@ namespace Awake.Core
|
|||||||
|
|
||||||
internal static void RunOnMainThread(Action action)
|
internal static void RunOnMainThread(Action action)
|
||||||
{
|
{
|
||||||
var syncContext = new SingleThreadSynchronizationContext();
|
_syncContext!.Post(
|
||||||
SynchronizationContext.SetSynchronizationContext(syncContext);
|
|
||||||
|
|
||||||
#pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type.
|
|
||||||
syncContext.Post(
|
|
||||||
_ =>
|
_ =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Logger.LogInfo($"Thread execution is on: {Environment.CurrentManagedThreadId}");
|
||||||
action();
|
action();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Error: " + e.Message);
|
Console.WriteLine("Error: " + e.Message);
|
||||||
}
|
}
|
||||||
finally
|
|
||||||
{
|
|
||||||
syncContext.EndMessageLoop();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
null);
|
null);
|
||||||
#pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type.
|
|
||||||
|
|
||||||
syncContext.BeginMessageLoop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SetTray(AwakeSettings settings, bool startedFromPowerToys)
|
internal static void SetTray(AwakeSettings settings, bool startedFromPowerToys)
|
||||||
@@ -353,6 +348,7 @@ namespace Awake.Core
|
|||||||
private static void CreateNewTrayMenu(bool startedFromPowerToys, bool keepDisplayOn, AwakeMode mode)
|
private static void CreateNewTrayMenu(bool startedFromPowerToys, bool keepDisplayOn, AwakeMode mode)
|
||||||
{
|
{
|
||||||
TrayMenu = Bridge.CreatePopupMenu();
|
TrayMenu = Bridge.CreatePopupMenu();
|
||||||
|
|
||||||
if (TrayMenu == IntPtr.Zero)
|
if (TrayMenu == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ namespace Awake
|
|||||||
{
|
{
|
||||||
_settingsUtils = new SettingsUtils();
|
_settingsUtils = new SettingsUtils();
|
||||||
LockMutex = new Mutex(true, Core.Constants.AppName, out bool instantiated);
|
LockMutex = new Mutex(true, Core.Constants.AppName, out bool instantiated);
|
||||||
|
|
||||||
Logger.InitializeLogger(Path.Combine("\\", Core.Constants.AppName, "Logs"));
|
Logger.InitializeLogger(Path.Combine("\\", Core.Constants.AppName, "Logs"));
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -71,17 +70,22 @@ namespace Awake
|
|||||||
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += AwakeUnhandledExceptionCatcher;
|
AppDomain.CurrentDomain.UnhandledException += AwakeUnhandledExceptionCatcher;
|
||||||
|
|
||||||
|
if (!instantiated)
|
||||||
|
{
|
||||||
|
// Awake is already running - there is no need for us to process
|
||||||
|
// anything further
|
||||||
|
Exit(Core.Constants.AppName + " is already running! Exiting the application.", 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredAwakeEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredAwakeEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
||||||
{
|
{
|
||||||
Exit("PowerToys.Awake tried to start with a group policy setting that disables the tool. Please contact your system administrator.", 1);
|
Exit("PowerToys.Awake tried to start with a group policy setting that disables the tool. Please contact your system administrator.", 1);
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!instantiated)
|
|
||||||
{
|
{
|
||||||
Exit(Core.Constants.AppName + " is already running! Exiting the application.", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.LogInfo($"Launching {Core.Constants.AppName}...");
|
Logger.LogInfo($"Launching {Core.Constants.AppName}...");
|
||||||
Logger.LogInfo(FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion);
|
Logger.LogInfo(FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion);
|
||||||
Logger.LogInfo($"Build: {Core.Constants.BuildId}");
|
Logger.LogInfo($"Build: {Core.Constants.BuildId}");
|
||||||
@@ -131,7 +135,7 @@ namespace Awake
|
|||||||
IsRequired = false,
|
IsRequired = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
var parentPidOption = new Option<bool>(AliasesParentPidOption, () => true, Resources.AWAKE_CMD_PARENT_PID_OPTION)
|
var parentPidOption = new Option<bool>(AliasesParentPidOption, () => false, Resources.AWAKE_CMD_PARENT_PID_OPTION)
|
||||||
{
|
{
|
||||||
Arity = ArgumentArity.ZeroOrOne,
|
Arity = ArgumentArity.ZeroOrOne,
|
||||||
IsRequired = false,
|
IsRequired = false,
|
||||||
@@ -152,6 +156,8 @@ namespace Awake
|
|||||||
|
|
||||||
return rootCommand.InvokeAsync(args).Result;
|
return rootCommand.InvokeAsync(args).Result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void AwakeUnhandledExceptionCatcher(object sender, UnhandledExceptionEventArgs e)
|
private static void AwakeUnhandledExceptionCatcher(object sender, UnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -180,15 +186,11 @@ namespace Awake
|
|||||||
if (pid == 0 && !useParentPid)
|
if (pid == 0 && !useParentPid)
|
||||||
{
|
{
|
||||||
Logger.LogInfo("No PID specified. Allocating console...");
|
Logger.LogInfo("No PID specified. Allocating console...");
|
||||||
Manager.AllocateConsole();
|
AllocateLocalConsole();
|
||||||
|
|
||||||
_handler += new ConsoleEventHandler(ExitHandler);
|
|
||||||
Manager.SetConsoleControlHandler(_handler, true);
|
|
||||||
|
|
||||||
Trace.Listeners.Add(new ConsoleTraceListener());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Logger.LogInfo("Starting with PID binding.");
|
||||||
_startedFromPowerToys = true;
|
_startedFromPowerToys = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +248,7 @@ namespace Awake
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogError($"There was a problem with the configuration file. Make sure it exists.\n{ex.Message}");
|
Logger.LogError($"There was a problem with the configuration file. Make sure it exists. {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pid != 0 || useParentPid)
|
else if (pid != 0 || useParentPid)
|
||||||
@@ -307,9 +309,31 @@ namespace Awake
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AllocateLocalConsole()
|
||||||
|
{
|
||||||
|
Manager.AllocateConsole();
|
||||||
|
|
||||||
|
_handler += new ConsoleEventHandler(ExitHandler);
|
||||||
|
Manager.SetConsoleControlHandler(_handler, true);
|
||||||
|
|
||||||
|
Trace.Listeners.Add(new ConsoleTraceListener());
|
||||||
|
}
|
||||||
|
|
||||||
private static void ScaffoldConfiguration(string settingsPath)
|
private static void ScaffoldConfiguration(string settingsPath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
SetupFileSystemWatcher(settingsPath);
|
||||||
|
InitializeSettings();
|
||||||
|
ProcessSettings();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError($"An error occurred scaffolding the configuration. Error details: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetupFileSystemWatcher(string settingsPath)
|
||||||
{
|
{
|
||||||
var directory = Path.GetDirectoryName(settingsPath)!;
|
var directory = Path.GetDirectoryName(settingsPath)!;
|
||||||
var fileName = Path.GetFileName(settingsPath);
|
var fileName = Path.GetFileName(settingsPath);
|
||||||
@@ -322,29 +346,23 @@ namespace Awake
|
|||||||
Filter = fileName,
|
Filter = fileName,
|
||||||
};
|
};
|
||||||
|
|
||||||
var mergedObservable = Observable.Merge(
|
Observable.Merge(
|
||||||
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
||||||
h => _watcher.Changed += h,
|
h => _watcher.Changed += h,
|
||||||
h => _watcher.Changed -= h),
|
h => _watcher.Changed -= h),
|
||||||
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
||||||
h => _watcher.Created += h,
|
h => _watcher.Created += h,
|
||||||
h => _watcher.Created -= h));
|
h => _watcher.Created -= h))
|
||||||
|
|
||||||
mergedObservable
|
|
||||||
.Throttle(TimeSpan.FromMilliseconds(25))
|
.Throttle(TimeSpan.FromMilliseconds(25))
|
||||||
.SubscribeOn(TaskPoolScheduler.Default)
|
.SubscribeOn(TaskPoolScheduler.Default)
|
||||||
.Select(e => e.EventArgs)
|
.Select(e => e.EventArgs)
|
||||||
.Subscribe(HandleAwakeConfigChange);
|
.Subscribe(HandleAwakeConfigChange);
|
||||||
|
|
||||||
var settings = Manager.ModuleSettings!.GetSettings<AwakeSettings>(Core.Constants.AppName) ?? new AwakeSettings();
|
|
||||||
TrayHelper.SetTray(settings, _startedFromPowerToys);
|
|
||||||
|
|
||||||
ProcessSettings();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
|
||||||
|
private static void InitializeSettings()
|
||||||
{
|
{
|
||||||
Logger.LogError($"An error occurred scaffolding the configuration. Error details: {ex.Message}");
|
var settings = Manager.ModuleSettings?.GetSettings<AwakeSettings>(Core.Constants.AppName) ?? new AwakeSettings();
|
||||||
}
|
TrayHelper.SetTray(settings, _startedFromPowerToys);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void HandleAwakeConfigChange(FileSystemEventArgs fileEvent)
|
private static void HandleAwakeConfigChange(FileSystemEventArgs fileEvent)
|
||||||
@@ -364,7 +382,9 @@ namespace Awake
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var settings = _settingsUtils!.GetSettings<AwakeSettings>(Core.Constants.AppName) ?? throw new InvalidOperationException("Settings are null.");
|
var settings = _settingsUtils!.GetSettings<AwakeSettings>(Core.Constants.AppName)
|
||||||
|
?? throw new InvalidOperationException("Settings are null.");
|
||||||
|
|
||||||
Logger.LogInfo($"Identified custom time shortcuts for the tray: {settings.Properties.CustomTrayTimes.Count}");
|
Logger.LogInfo($"Identified custom time shortcuts for the tray: {settings.Properties.CustomTrayTimes.Count}");
|
||||||
|
|
||||||
switch (settings.Properties.Mode)
|
switch (settings.Properties.Mode)
|
||||||
@@ -378,7 +398,7 @@ namespace Awake
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AwakeMode.TIMED:
|
case AwakeMode.TIMED:
|
||||||
uint computedTime = (settings.Properties.IntervalHours * 60 * 60) + (settings.Properties.IntervalMinutes * 60);
|
uint computedTime = (settings.Properties.IntervalHours * 3600) + (settings.Properties.IntervalMinutes * 60);
|
||||||
Manager.SetTimedKeepAwake(computedTime, settings.Properties.KeepDisplayOn);
|
Manager.SetTimedKeepAwake(computedTime, settings.Properties.KeepDisplayOn);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user