mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 18:26:39 +02:00
Espresso (#11303)
* Update README.md * Espresso (#11245) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Update Product.wxs * Update Shortcut.cpp * Update with more logging (#11332) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso * Adding some extra logging * Update Shortcut.cpp Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Fix minor issue in the module branch (#11340) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso * Adding some extra logging * Update Shortcut.cpp * Fix log location coming from the runner * More chatty logging for console allocation * Installer config to add the missing assets Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Update Product.wxs * Update Program.cs * fixing typo * removing a unneeded removal * [Espresso] More minor tweaks to logging (#11341) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso * Adding some extra logging * Update Shortcut.cpp * Fix log location coming from the runner * More chatty logging for console allocation * Installer config to add the missing assets * Remove unused handle codes * Update log file name for the Espresso C++ code. * Update the project configuration to fix build issue Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Update patterns.txt * Fix binding issues (#11368) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso * Adding some extra logging * Update Shortcut.cpp * Fix log location coming from the runner * More chatty logging for console allocation * Installer config to add the missing assets * Remove unused handle codes * Update log file name for the Espresso C++ code. * Update the project configuration to fix build issue * Fix binding issue with the time settings Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Introduce the off mode and fix binding issues (#11385) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso * Adding some extra logging * Update Shortcut.cpp * Fix log location coming from the runner * More chatty logging for console allocation * Installer config to add the missing assets * Remove unused handle codes * Update log file name for the Espresso C++ code. * Update the project configuration to fix build issue * Fix binding issue with the time settings * Proper Espresso behavior for binding * Fix settings UI Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Update with missing strings. (#11386) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso * Adding some extra logging * Update Shortcut.cpp * Fix log location coming from the runner * More chatty logging for console allocation * Installer config to add the missing assets * Remove unused handle codes * Update log file name for the Espresso C++ code. * Update the project configuration to fix build issue * Fix binding issue with the time settings * Proper Espresso behavior for binding * Fix settings UI * Re-add missing strings Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Fix whitespace issue (#11387) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso * Adding some extra logging * Update Shortcut.cpp * Fix log location coming from the runner * More chatty logging for console allocation * Installer config to add the missing assets * Remove unused handle codes * Update log file name for the Espresso C++ code. * Update the project configuration to fix build issue * Fix binding issue with the time settings * Proper Espresso behavior for binding * Fix settings UI * Re-add missing strings * Fix whitespace issue Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Fix default (#11388) * Revert "Merge branch 'microsoft:master' into master" This reverts commitb080908712, reversing changes made to8463c95a43. * Fix conversion of settings in the UX * Update terminology * Updating logging configuration * Set up how tray and setting configuration works * Adding hero images * Fix how binding works * Update OOBE string * Fix spelling error * fixing dep to include espresso, adding in yml * Update API components and fix display keep-awake bug * Adding words that the spell check is yelling about * tweak wsx * Change default setting for Espresso * Adding some extra logging * Update Shortcut.cpp * Fix log location coming from the runner * More chatty logging for console allocation * Installer config to add the missing assets * Remove unused handle codes * Update log file name for the Espresso C++ code. * Update the project configuration to fix build issue * Fix binding issue with the time settings * Proper Espresso behavior for binding * Fix settings UI * Re-add missing strings * Fix whitespace issue * Fix the default mode of operation Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> * Update Microsoft.PowerToys.Settings.UI.csproj * Localization improvements * Replaced a computer with your pc * Updated Espresso imagery * Fixed inconsistent string * Margin fix and updated images * Removed unused code Co-authored-by: Den Delimarsky <1389609+dend@users.noreply.github.com> Co-authored-by: Niels Laute <niels9001@hotmail.com> Co-authored-by: crutkas <crutkas@microsoft.com> Co-authored-by: Enrico Giordani <enrico.giordani@gmail.com>
This commit is contained in:
280
src/modules/espresso/Espresso/Core/APIHelper.cs
Normal file
280
src/modules/espresso/Espresso/Core/APIHelper.cs
Normal file
@@ -0,0 +1,280 @@
|
||||
// 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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Win32;
|
||||
using NLog;
|
||||
|
||||
namespace Espresso.Shell.Core
|
||||
{
|
||||
[Flags]
|
||||
public enum EXECUTION_STATE : uint
|
||||
{
|
||||
ES_AWAYMODE_REQUIRED = 0x00000040,
|
||||
ES_CONTINUOUS = 0x80000000,
|
||||
ES_DISPLAY_REQUIRED = 0x00000002,
|
||||
ES_SYSTEM_REQUIRED = 0x00000001,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper class that allows talking to Win32 APIs without having to rely on PInvoke in other parts
|
||||
/// of the codebase.
|
||||
/// </summary>
|
||||
public class APIHelper
|
||||
{
|
||||
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 CancellationTokenSource _tokenSource;
|
||||
private static CancellationToken _threadToken;
|
||||
|
||||
private static Task? _runnerThread;
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool AllocConsole();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern uint GetCurrentThreadId();
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
private static extern IntPtr CreateFile(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] 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);
|
||||
|
||||
static APIHelper()
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_tokenSource = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
public static void AllocateConsole()
|
||||
{
|
||||
_log.Debug("Bootstrapping the console allocation routine.");
|
||||
AllocConsole();
|
||||
_log.Debug($"Console allocation result: {Marshal.GetLastWin32Error()}");
|
||||
|
||||
var outputFilePointer = CreateFile("CONOUT$", GenericRead | GenericWrite, FileShare.Write, IntPtr.Zero, FileMode.OpenOrCreate, 0, IntPtr.Zero);
|
||||
_log.Debug($"CONOUT creation result: {Marshal.GetLastWin32Error()}");
|
||||
|
||||
SetStdHandle(StdOutputHandle, outputFilePointer);
|
||||
_log.Debug($"SetStdHandle result: {Marshal.GetLastWin32Error()}");
|
||||
|
||||
Console.SetOut(new StreamWriter(Console.OpenStandardOutput(), Console.OutputEncoding) { AutoFlush = true });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the computer awake state using the native Win32 SetThreadExecutionState API. This
|
||||
/// function is just a nice-to-have wrapper that helps avoid tracking the success or failure of
|
||||
/// the call.
|
||||
/// </summary>
|
||||
/// <param name="state">Single or multiple EXECUTION_STATE entries.</param>
|
||||
/// <returns>true if successful, false if failed</returns>
|
||||
private static bool SetAwakeState(EXECUTION_STATE state)
|
||||
{
|
||||
try
|
||||
{
|
||||
var stateResult = SetThreadExecutionState(state);
|
||||
return stateResult != 0;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetIndefiniteKeepAwake(Action<bool> callback, Action failureCallback, bool keepDisplayOn = false)
|
||||
{
|
||||
_tokenSource.Cancel();
|
||||
|
||||
try
|
||||
{
|
||||
if (_runnerThread != null && !_runnerThread.IsCanceled)
|
||||
{
|
||||
_runnerThread.Wait(_threadToken);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_log.Info("Confirmed background thread cancellation when setting indefinite keep awake.");
|
||||
}
|
||||
|
||||
_tokenSource = new CancellationTokenSource();
|
||||
_threadToken = _tokenSource.Token;
|
||||
|
||||
_runnerThread = Task.Run(() => RunIndefiniteLoop(keepDisplayOn), _threadToken)
|
||||
.ContinueWith((result) => callback(result.Result), TaskContinuationOptions.OnlyOnRanToCompletion)
|
||||
.ContinueWith((result) => failureCallback, TaskContinuationOptions.NotOnRanToCompletion);
|
||||
}
|
||||
|
||||
public static void SetNoKeepAwake()
|
||||
{
|
||||
_tokenSource.Cancel();
|
||||
|
||||
try
|
||||
{
|
||||
if (_runnerThread != null && !_runnerThread.IsCanceled)
|
||||
{
|
||||
_runnerThread.Wait(_threadToken);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_log.Info("Confirmed background thread cancellation when setting passive keep awake.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetTimedKeepAwake(uint seconds, Action<bool> callback, Action failureCallback, bool keepDisplayOn = true)
|
||||
{
|
||||
_tokenSource.Cancel();
|
||||
|
||||
try
|
||||
{
|
||||
if (_runnerThread != null && !_runnerThread.IsCanceled)
|
||||
{
|
||||
_runnerThread.Wait(_threadToken);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_log.Info("Confirmed background thread cancellation when setting indefinite keep awake.");
|
||||
}
|
||||
|
||||
_tokenSource = new CancellationTokenSource();
|
||||
_threadToken = _tokenSource.Token;
|
||||
|
||||
_runnerThread = Task.Run(() => RunTimedLoop(seconds, keepDisplayOn), _threadToken)
|
||||
.ContinueWith((result) => callback(result.Result), TaskContinuationOptions.OnlyOnRanToCompletion)
|
||||
.ContinueWith((result) => failureCallback, TaskContinuationOptions.NotOnRanToCompletion);
|
||||
}
|
||||
|
||||
private static bool RunIndefiniteLoop(bool keepDisplayOn = false)
|
||||
{
|
||||
bool success;
|
||||
if (keepDisplayOn)
|
||||
{
|
||||
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
_log.Info($"Initiated indefinite keep awake in background thread: {GetCurrentThreadId()}. Screen on: {keepDisplayOn}");
|
||||
while (true)
|
||||
{
|
||||
if (_threadToken.IsCancellationRequested)
|
||||
{
|
||||
_threadToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.Info("Could not successfully set up indefinite keep awake.");
|
||||
return success;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
// Task was clearly cancelled.
|
||||
_log.Info($"Background thread termination: {GetCurrentThreadId()}. Message: {ex.Message}");
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool RunTimedLoop(uint seconds, bool keepDisplayOn = true)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// In case cancellation was already requested.
|
||||
_threadToken.ThrowIfCancellationRequested();
|
||||
try
|
||||
{
|
||||
if (keepDisplayOn)
|
||||
{
|
||||
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
|
||||
}
|
||||
else
|
||||
{
|
||||
success = SetAwakeState(EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
_log.Info($"Initiated temporary keep awake in background thread: {GetCurrentThreadId()}. Screen on: {keepDisplayOn}");
|
||||
var startTime = DateTime.UtcNow;
|
||||
while (DateTime.UtcNow - startTime < TimeSpan.FromSeconds(Math.Abs(seconds)))
|
||||
{
|
||||
if (_threadToken.IsCancellationRequested)
|
||||
{
|
||||
_threadToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.Info("Could not set up timed keep-awake with display on.");
|
||||
return success;
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
// Task was clearly cancelled.
|
||||
_log.Info($"Background thread termination: {GetCurrentThreadId()}. Message: {ex.Message}");
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetOperatingSystemBuild()
|
||||
{
|
||||
try
|
||||
{
|
||||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(BuildRegistryLocation);
|
||||
#pragma warning restore CS8600 // Converting null literal or possible null value to non-nullable type.
|
||||
|
||||
if (registryKey != null)
|
||||
{
|
||||
var versionString = $"{registryKey.GetValue("ProductName")} {registryKey.GetValue("DisplayVersion")} {registryKey.GetValue("BuildLabEx")}";
|
||||
return versionString;
|
||||
}
|
||||
else
|
||||
{
|
||||
_log.Info("Registry key acquisition for OS failed.");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Info($"Could not get registry key for the build number. Error: {ex.Message}");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
297
src/modules/espresso/Espresso/Core/TrayHelper.cs
Normal file
297
src/modules/espresso/Espresso/Core/TrayHelper.cs
Normal file
@@ -0,0 +1,297 @@
|
||||
// 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.Drawing;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Windows.Forms;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
|
||||
namespace Espresso.Shell.Core
|
||||
{
|
||||
internal static class TrayHelper
|
||||
{
|
||||
private static NotifyIcon? trayIcon;
|
||||
|
||||
private static NotifyIcon TrayIcon { get => trayIcon; set => trayIcon = value; }
|
||||
|
||||
private static SettingsUtils? moduleSettings;
|
||||
|
||||
private static SettingsUtils ModuleSettings { get => moduleSettings; set => moduleSettings = value; }
|
||||
|
||||
static TrayHelper()
|
||||
{
|
||||
TrayIcon = new NotifyIcon();
|
||||
ModuleSettings = new SettingsUtils();
|
||||
}
|
||||
|
||||
public static void InitializeTray(string text, Icon icon, ContextMenuStrip? contextMenu = null)
|
||||
{
|
||||
System.Threading.Tasks.Task.Factory.StartNew(
|
||||
(tray) =>
|
||||
{
|
||||
((NotifyIcon?)tray).Text = text;
|
||||
((NotifyIcon?)tray).Icon = icon;
|
||||
((NotifyIcon?)tray).ContextMenuStrip = contextMenu;
|
||||
((NotifyIcon?)tray).Visible = true;
|
||||
|
||||
Application.Run();
|
||||
}, TrayIcon);
|
||||
}
|
||||
|
||||
internal static void SetTray(string text, EspressoSettings settings)
|
||||
{
|
||||
SetTray(
|
||||
text,
|
||||
settings.Properties.KeepDisplayOn,
|
||||
settings.Properties.Mode,
|
||||
PassiveKeepAwakeCallback(text),
|
||||
IndefiniteKeepAwakeCallback(text),
|
||||
TimedKeepAwakeCallback(text),
|
||||
KeepDisplayOnCallback(text),
|
||||
ExitCallback());
|
||||
}
|
||||
|
||||
private static Action ExitCallback()
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
Environment.Exit(0);
|
||||
};
|
||||
}
|
||||
|
||||
private static Action KeepDisplayOnCallback(string moduleName)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
EspressoSettings currentSettings;
|
||||
|
||||
try
|
||||
{
|
||||
currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
currentSettings = new EspressoSettings();
|
||||
}
|
||||
|
||||
currentSettings.Properties.KeepDisplayOn = !currentSettings.Properties.KeepDisplayOn;
|
||||
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
};
|
||||
}
|
||||
|
||||
private static Action<uint, uint> TimedKeepAwakeCallback(string moduleName)
|
||||
{
|
||||
return (hours, minutes) =>
|
||||
{
|
||||
EspressoSettings currentSettings;
|
||||
|
||||
try
|
||||
{
|
||||
currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
currentSettings = new EspressoSettings();
|
||||
}
|
||||
|
||||
currentSettings.Properties.Mode = EspressoMode.TIMED;
|
||||
currentSettings.Properties.Hours = hours;
|
||||
currentSettings.Properties.Minutes = minutes;
|
||||
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
};
|
||||
}
|
||||
|
||||
private static Action PassiveKeepAwakeCallback(string moduleName)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
EspressoSettings currentSettings;
|
||||
|
||||
try
|
||||
{
|
||||
currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
currentSettings = new EspressoSettings();
|
||||
}
|
||||
|
||||
currentSettings.Properties.Mode = EspressoMode.PASSIVE;
|
||||
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
};
|
||||
}
|
||||
|
||||
private static Action IndefiniteKeepAwakeCallback(string moduleName)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
EspressoSettings currentSettings;
|
||||
|
||||
try
|
||||
{
|
||||
currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
currentSettings = new EspressoSettings();
|
||||
}
|
||||
|
||||
currentSettings.Properties.Mode = EspressoMode.INDEFINITE;
|
||||
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
};
|
||||
}
|
||||
|
||||
public static void SetTray(string text, bool keepDisplayOn, EspressoMode mode, Action passiveKeepAwakeCallback, Action indefiniteKeepAwakeCallback, Action<uint, uint> timedKeepAwakeCallback, Action keepDisplayOnCallback, Action exitCallback)
|
||||
{
|
||||
var contextMenuStrip = new ContextMenuStrip();
|
||||
|
||||
// Main toolstrip.
|
||||
var operationContextMenu = new ToolStripMenuItem
|
||||
{
|
||||
Text = "Mode",
|
||||
};
|
||||
|
||||
// No keep-awake menu item.
|
||||
var passiveMenuItem = new ToolStripMenuItem
|
||||
{
|
||||
Text = "Off (Passive)",
|
||||
};
|
||||
|
||||
if (mode == EspressoMode.PASSIVE)
|
||||
{
|
||||
passiveMenuItem.Checked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
passiveMenuItem.Checked = false;
|
||||
}
|
||||
|
||||
passiveMenuItem.Click += (e, s) =>
|
||||
{
|
||||
// User opted to set the mode to indefinite, so we need to write new settings.
|
||||
passiveKeepAwakeCallback();
|
||||
};
|
||||
|
||||
// Indefinite keep-awake menu item.
|
||||
var indefiniteMenuItem = new ToolStripMenuItem
|
||||
{
|
||||
Text = "Keep awake indefinitely",
|
||||
};
|
||||
|
||||
if (mode == EspressoMode.INDEFINITE)
|
||||
{
|
||||
indefiniteMenuItem.Checked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
indefiniteMenuItem.Checked = false;
|
||||
}
|
||||
|
||||
indefiniteMenuItem.Click += (e, s) =>
|
||||
{
|
||||
// User opted to set the mode to indefinite, so we need to write new settings.
|
||||
indefiniteKeepAwakeCallback();
|
||||
};
|
||||
|
||||
var displayOnMenuItem = new ToolStripMenuItem
|
||||
{
|
||||
Text = "Keep screen on",
|
||||
};
|
||||
if (keepDisplayOn)
|
||||
{
|
||||
displayOnMenuItem.Checked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
displayOnMenuItem.Checked = false;
|
||||
}
|
||||
|
||||
displayOnMenuItem.Click += (e, s) =>
|
||||
{
|
||||
// User opted to set the display mode directly.
|
||||
keepDisplayOnCallback();
|
||||
};
|
||||
|
||||
// Timed keep-awake menu item
|
||||
var timedMenuItem = new ToolStripMenuItem
|
||||
{
|
||||
Text = "Keep awake temporarily",
|
||||
};
|
||||
if (mode == EspressoMode.TIMED)
|
||||
{
|
||||
timedMenuItem.Checked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
timedMenuItem.Checked = false;
|
||||
}
|
||||
|
||||
var halfHourMenuItem = new ToolStripMenuItem
|
||||
{
|
||||
Text = "30 minutes",
|
||||
};
|
||||
halfHourMenuItem.Click += (e, s) =>
|
||||
{
|
||||
// User is setting the keep-awake to 30 minutes.
|
||||
timedKeepAwakeCallback(0, 30);
|
||||
};
|
||||
|
||||
var oneHourMenuItem = new ToolStripMenuItem
|
||||
{
|
||||
Text = "1 hour",
|
||||
};
|
||||
oneHourMenuItem.Click += (e, s) =>
|
||||
{
|
||||
// User is setting the keep-awake to 1 hour.
|
||||
timedKeepAwakeCallback(1, 0);
|
||||
};
|
||||
|
||||
var twoHoursMenuItem = new ToolStripMenuItem
|
||||
{
|
||||
Text = "2 hours",
|
||||
};
|
||||
twoHoursMenuItem.Click += (e, s) =>
|
||||
{
|
||||
// User is setting the keep-awake to 2 hours.
|
||||
timedKeepAwakeCallback(2, 0);
|
||||
};
|
||||
|
||||
// Exit menu item.
|
||||
var exitContextMenu = new ToolStripMenuItem
|
||||
{
|
||||
Text = "Exit",
|
||||
};
|
||||
exitContextMenu.Click += (e, s) =>
|
||||
{
|
||||
// User is setting the keep-awake to 2 hours.
|
||||
exitCallback();
|
||||
};
|
||||
|
||||
timedMenuItem.DropDownItems.Add(halfHourMenuItem);
|
||||
timedMenuItem.DropDownItems.Add(oneHourMenuItem);
|
||||
timedMenuItem.DropDownItems.Add(twoHoursMenuItem);
|
||||
|
||||
operationContextMenu.DropDownItems.Add(passiveMenuItem);
|
||||
operationContextMenu.DropDownItems.Add(indefiniteMenuItem);
|
||||
operationContextMenu.DropDownItems.Add(timedMenuItem);
|
||||
|
||||
contextMenuStrip.Items.Add(operationContextMenu);
|
||||
contextMenuStrip.Items.Add(displayOnMenuItem);
|
||||
contextMenuStrip.Items.Add(new ToolStripSeparator());
|
||||
contextMenuStrip.Items.Add(exitContextMenu);
|
||||
|
||||
TrayIcon.Text = text;
|
||||
TrayIcon.ContextMenuStrip = contextMenuStrip;
|
||||
}
|
||||
}
|
||||
}
|
||||
83
src/modules/espresso/Espresso/Espresso.csproj
Normal file
83
src/modules/espresso/Espresso/Espresso.csproj
Normal file
@@ -0,0 +1,83 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\Espresso</OutputPath>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>x64</Platforms>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<!--Per documentation: https://docs.microsoft.com/dotnet/core/compatibility/windows-forms/5.0/automatically-infer-winexe-output-type#outputtype-set-to-winexe-for-wpf-and-winforms-apps -->
|
||||
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
|
||||
<AssemblyName>PowerToys.Espresso</AssemblyName>
|
||||
<Version>$(Version).0</Version>
|
||||
<ApplicationIcon>Images\Espresso.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Optimize>false</Optimize>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<DefineConstants>TRACE;RELEASE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<PackageReference Include="NLog" Version="4.7.9" />
|
||||
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20071.2" />
|
||||
<PackageReference Include="System.Reactive" Version="5.0.0" />
|
||||
<PackageReference Include="System.Runtime.Caching" Version="6.0.0-preview.1.21102.12" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\..\settings-ui\Microsoft.PowerToys.Settings.UI.Library\Microsoft.PowerToys.Settings.UI.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Program.cs">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="NLog.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\codeAnalysis\GlobalSuppressions.cs">
|
||||
<Link>GlobalSuppressions.cs</Link>
|
||||
</Compile>
|
||||
<AdditionalFiles Include="..\..\..\codeAnalysis\StyleCop.json">
|
||||
<Link>StyleCop.json</Link>
|
||||
</AdditionalFiles>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="StyleCop.Analyzers">
|
||||
<Version>1.1.118</Version>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\Espresso.ico" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
BIN
src/modules/espresso/Espresso/Images/Espresso.ico
Normal file
BIN
src/modules/espresso/Espresso/Images/Espresso.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
22
src/modules/espresso/Espresso/NLog.config
Normal file
22
src/modules/espresso/Espresso/NLog.config
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<variable name="espressoversion" value="0.0.1" />
|
||||
|
||||
<targets async="true">
|
||||
<target name="logfile"
|
||||
xsi:type="File"
|
||||
fileName="${specialfolder:folder=LocalApplicationData}/Microsoft/PowerToys/Espresso/Logs/${var:espressoversion}/log_${date:format=yyyy-MM-dd_HH}_DBG.txt"
|
||||
layout="[${longdate} ${level:uppercase=true} ${logger}] ${message}"
|
||||
archiveEvery="Day"
|
||||
archiveNumbering="Rolling"
|
||||
maxArchiveFiles="30"/>
|
||||
<target name="logconsole" xsi:type="Console" layout="[${longdate} ${level:uppercase=true}] ${message}" />
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
<logger name="*" minlevel="Info" writeTo="logconsole" />
|
||||
<logger name="*" minlevel="Debug" writeTo="logfile" />
|
||||
</rules>
|
||||
</nlog>
|
||||
320
src/modules/espresso/Espresso/Program.cs
Normal file
320
src/modules/espresso/Espresso/Program.cs
Normal file
@@ -0,0 +1,320 @@
|
||||
// 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.CommandLine;
|
||||
using System.CommandLine.Invocation;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive.Concurrency;
|
||||
using System.Reactive.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using Espresso.Shell.Core;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using NLog;
|
||||
|
||||
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
||||
#pragma warning disable CS8603 // Possible null reference return.
|
||||
|
||||
namespace Espresso.Shell
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
private static Mutex? _mutex = null;
|
||||
private const string AppName = "Espresso";
|
||||
private static FileSystemWatcher? _watcher = null;
|
||||
private static SettingsUtils? _settingsUtils = null;
|
||||
|
||||
public static Mutex LockMutex { get => _mutex; set => _mutex = value; }
|
||||
|
||||
private static Logger? _log;
|
||||
|
||||
private static int Main(string[] args)
|
||||
{
|
||||
bool instantiated;
|
||||
LockMutex = new Mutex(true, AppName, out instantiated);
|
||||
|
||||
if (!instantiated)
|
||||
{
|
||||
ForceExit(AppName + " is already running! Exiting the application.", 1);
|
||||
}
|
||||
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_settingsUtils = new SettingsUtils();
|
||||
|
||||
_log.Info("Launching Espresso...");
|
||||
_log.Info(FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion);
|
||||
_log.Info($"OS: {Environment.OSVersion}");
|
||||
_log.Info($"OS Build: {APIHelper.GetOperatingSystemBuild()}");
|
||||
|
||||
_log.Info("Parsing parameters...");
|
||||
|
||||
var configOption = new Option<bool>(
|
||||
aliases: new[] { "--use-pt-config", "-c" },
|
||||
getDefaultValue: () => false,
|
||||
description: "Specifies whether Espresso will be using the PowerToys configuration file for managing the state.")
|
||||
{
|
||||
Argument = new Argument<bool>(() => false)
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
},
|
||||
};
|
||||
|
||||
configOption.Required = false;
|
||||
|
||||
var displayOption = new Option<bool>(
|
||||
aliases: new[] { "--display-on", "-d" },
|
||||
getDefaultValue: () => true,
|
||||
description: "Determines whether the display should be kept awake.")
|
||||
{
|
||||
Argument = new Argument<bool>(() => false)
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
},
|
||||
};
|
||||
|
||||
displayOption.Required = false;
|
||||
|
||||
var timeOption = new Option<uint>(
|
||||
aliases: new[] { "--time-limit", "-t" },
|
||||
getDefaultValue: () => 0,
|
||||
description: "Determines the interval, in seconds, during which the computer is kept awake.")
|
||||
{
|
||||
Argument = new Argument<uint>(() => 0)
|
||||
{
|
||||
Arity = ArgumentArity.ExactlyOne,
|
||||
},
|
||||
};
|
||||
|
||||
timeOption.Required = false;
|
||||
|
||||
var pidOption = new Option<int>(
|
||||
aliases: new[] { "--pid", "-p" },
|
||||
getDefaultValue: () => 0,
|
||||
description: "Bind the execution of Espresso to another process.")
|
||||
{
|
||||
Argument = new Argument<int>(() => 0)
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
},
|
||||
};
|
||||
|
||||
pidOption.Required = false;
|
||||
|
||||
var rootCommand = new RootCommand
|
||||
{
|
||||
configOption,
|
||||
displayOption,
|
||||
timeOption,
|
||||
pidOption,
|
||||
};
|
||||
|
||||
rootCommand.Description = AppName;
|
||||
|
||||
rootCommand.Handler = CommandHandler.Create<bool, bool, uint, int>(HandleCommandLineArguments);
|
||||
|
||||
_log.Info("Parameter setup complete. Proceeding to the rest of the app initiation...");
|
||||
|
||||
return rootCommand.InvokeAsync(args).Result;
|
||||
}
|
||||
|
||||
private static void ForceExit(string message, int exitCode)
|
||||
{
|
||||
_log.Info(message);
|
||||
Console.ReadKey();
|
||||
Environment.Exit(exitCode);
|
||||
}
|
||||
|
||||
private static void HandleCommandLineArguments(bool usePtConfig, bool displayOn, uint timeLimit, int pid)
|
||||
{
|
||||
if (pid == 0)
|
||||
{
|
||||
_log.Info("No PID specified. Allocating console...");
|
||||
APIHelper.AllocateConsole();
|
||||
}
|
||||
|
||||
_log.Info($"The value for --use-pt-config is: {usePtConfig}");
|
||||
_log.Info($"The value for --display-on is: {displayOn}");
|
||||
_log.Info($"The value for --time-limit is: {timeLimit}");
|
||||
_log.Info($"The value for --pid is: {pid}");
|
||||
|
||||
if (usePtConfig)
|
||||
{
|
||||
// Configuration file is used, therefore we disregard any other command-line parameter
|
||||
// and instead watch for changes in the file.
|
||||
try
|
||||
{
|
||||
#pragma warning disable CS8604 // Possible null reference argument.
|
||||
TrayHelper.InitializeTray(AppName, new Icon(Application.GetResourceStream(new Uri("/Images/Espresso.ico", UriKind.Relative)).Stream));
|
||||
#pragma warning restore CS8604 // Possible null reference argument.
|
||||
|
||||
var settingsPath = _settingsUtils.GetSettingsFilePath(AppName);
|
||||
_log.Info($"Reading configuration file: {settingsPath}");
|
||||
|
||||
_watcher = new FileSystemWatcher
|
||||
{
|
||||
Path = Path.GetDirectoryName(settingsPath),
|
||||
EnableRaisingEvents = true,
|
||||
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime,
|
||||
Filter = Path.GetFileName(settingsPath),
|
||||
};
|
||||
|
||||
var changedObservable = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
||||
h => _watcher.Changed += h,
|
||||
h => _watcher.Changed -= h);
|
||||
|
||||
var createdObservable = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
|
||||
cre => _watcher.Created += cre,
|
||||
cre => _watcher.Created -= cre);
|
||||
|
||||
var mergedObservable = Observable.Merge(changedObservable, createdObservable);
|
||||
|
||||
mergedObservable.Throttle(TimeSpan.FromMilliseconds(25))
|
||||
.SubscribeOn(TaskPoolScheduler.Default)
|
||||
.Select(e => e.EventArgs)
|
||||
.Subscribe(HandleEspressoConfigChange);
|
||||
|
||||
TrayHelper.SetTray(AppName, new EspressoSettings());
|
||||
|
||||
// Initially the file might not be updated, so we need to start processing
|
||||
// settings right away.
|
||||
ProcessSettings();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorString = $"There was a problem with the configuration file. Make sure it exists.\n{ex.Message}";
|
||||
_log.Info(errorString);
|
||||
_log.Debug(errorString);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var mode = timeLimit <= 0 ? EspressoMode.INDEFINITE : EspressoMode.TIMED;
|
||||
|
||||
if (mode == EspressoMode.INDEFINITE)
|
||||
{
|
||||
SetupIndefiniteKeepAwake(displayOn);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupTimedKeepAwake(timeLimit, displayOn);
|
||||
}
|
||||
}
|
||||
|
||||
var exitSignal = new ManualResetEvent(false);
|
||||
if (pid != 0)
|
||||
{
|
||||
RunnerHelper.WaitForPowerToysRunner(pid, () =>
|
||||
{
|
||||
exitSignal.Set();
|
||||
Environment.Exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
exitSignal.WaitOne();
|
||||
}
|
||||
|
||||
private static void SetupIndefiniteKeepAwake(bool displayOn)
|
||||
{
|
||||
// Indefinite keep awake.
|
||||
APIHelper.SetIndefiniteKeepAwake(LogCompletedKeepAwakeThread, LogUnexpectedOrCancelledKeepAwakeThreadCompletion, displayOn);
|
||||
}
|
||||
|
||||
private static void HandleEspressoConfigChange(FileSystemEventArgs fileEvent)
|
||||
{
|
||||
_log.Info("Detected a settings file change. Updating configuration...");
|
||||
_log.Info("Resetting keep-awake to normal state due to settings change.");
|
||||
ProcessSettings();
|
||||
}
|
||||
|
||||
private static void ProcessSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
EspressoSettings settings = _settingsUtils.GetSettings<EspressoSettings>(AppName);
|
||||
|
||||
if (settings != null)
|
||||
{
|
||||
switch (settings.Properties.Mode)
|
||||
{
|
||||
case EspressoMode.PASSIVE:
|
||||
{
|
||||
SetupNoKeepAwake();
|
||||
break;
|
||||
}
|
||||
|
||||
case EspressoMode.INDEFINITE:
|
||||
{
|
||||
// Indefinite keep awake.
|
||||
SetupIndefiniteKeepAwake(settings.Properties.KeepDisplayOn);
|
||||
break;
|
||||
}
|
||||
|
||||
case EspressoMode.TIMED:
|
||||
{
|
||||
// Timed keep-awake.
|
||||
uint computedTime = (settings.Properties.Hours * 60 * 60) + (settings.Properties.Minutes * 60);
|
||||
SetupTimedKeepAwake(computedTime, settings.Properties.KeepDisplayOn);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
var errorMessage = "Unknown mode of operation. Check config file.";
|
||||
_log.Info(errorMessage);
|
||||
_log.Debug(errorMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TrayHelper.SetTray(AppName, settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
var errorMessage = "Settings are null.";
|
||||
_log.Info(errorMessage);
|
||||
_log.Debug(errorMessage);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var errorMessage = $"There was a problem reading the configuration file. Error: {ex.GetType()} {ex.Message}";
|
||||
_log.Info(errorMessage);
|
||||
_log.Debug(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetupNoKeepAwake()
|
||||
{
|
||||
_log.Info($"Operating in passive mode (computer's standard power plan). No custom keep awake settings enabled.");
|
||||
|
||||
APIHelper.SetNoKeepAwake();
|
||||
}
|
||||
|
||||
private static void SetupTimedKeepAwake(uint time, bool displayOn)
|
||||
{
|
||||
_log.Info($"Timed keep-awake. Expected runtime: {time} seconds with display on setting set to {displayOn}.");
|
||||
|
||||
APIHelper.SetTimedKeepAwake(time, LogCompletedKeepAwakeThread, LogUnexpectedOrCancelledKeepAwakeThreadCompletion, displayOn);
|
||||
}
|
||||
|
||||
private static void LogUnexpectedOrCancelledKeepAwakeThreadCompletion()
|
||||
{
|
||||
var errorMessage = "The keep-awake thread was terminated early.";
|
||||
_log.Info(errorMessage);
|
||||
_log.Debug(errorMessage);
|
||||
}
|
||||
|
||||
private static void LogCompletedKeepAwakeThread(bool result)
|
||||
{
|
||||
_log.Info($"Exited keep-awake thread successfully: {result}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <string>
|
||||
|
||||
namespace EspressoConstants
|
||||
{
|
||||
// Name of the powertoy module.
|
||||
inline const std::wstring ModuleKey = L"Espresso";
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_ESPRESSO_NAME "Espresso"
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{5e7360a8-d048-4ed3-8f09-0bfd64c5529a}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>Espresso</RootNamespace>
|
||||
<ProjectName>EspressoModuleInterface</ProjectName>
|
||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\Espresso\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="EspressoConstants.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trace.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EspressoModuleInterface.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EspressoConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{e8ef1c4e-cc50-4ce5-b00d-4e3ac5c1a7db}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{fbd9cdd2-e7d5-4417-9b52-25e345ae9562}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{c2a23a2b-5846-440f-b29e-eea748dba12d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{77f1702b-da7f-4ff6-90a3-19db515cf963}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EspressoModuleInterface.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
181
src/modules/espresso/EspressoModuleInterface/dllmain.cpp
Normal file
181
src/modules/espresso/EspressoModuleInterface/dllmain.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
#include "pch.h"
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include <common/interop/shared_constants.h>
|
||||
#include "trace.h"
|
||||
#include "resource.h"
|
||||
#include "EspressoConstants.h"
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <common/utils/os-detect.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
Trace::RegisterProvider();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
Trace::UnregisterProvider();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// The PowerToy name that will be shown in the settings.
|
||||
const static wchar_t* MODULE_NAME = L"Espresso";
|
||||
|
||||
// Add a description that will we shown in the module settings page.
|
||||
const static wchar_t* MODULE_DESC = L"<no description>";
|
||||
|
||||
// Implement the PowerToy Module Interface and all the required methods.
|
||||
class Espresso : public PowertoyModuleIface
|
||||
{
|
||||
std::wstring app_name;
|
||||
|
||||
// Contains the non localized key of the powertoy
|
||||
std::wstring app_key;
|
||||
|
||||
private:
|
||||
// The PowerToy state.
|
||||
bool m_enabled = false;
|
||||
|
||||
HANDLE m_hProcess;
|
||||
|
||||
HANDLE send_telemetry_event;
|
||||
|
||||
// Handle to event used to invoke Espresso
|
||||
HANDLE m_hInvokeEvent;
|
||||
|
||||
bool is_process_running()
|
||||
{
|
||||
return WaitForSingleObject(m_hProcess, 0) == WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
void launch_process()
|
||||
{
|
||||
Logger::trace(L"Launching Espresso process");
|
||||
unsigned long powertoys_pid = GetCurrentProcessId();
|
||||
|
||||
std::wstring executable_args = L"--use-pt-config --pid " + std::to_wstring(powertoys_pid);
|
||||
Logger::trace(L"Espresso launching with parameters: " + executable_args);
|
||||
|
||||
SHELLEXECUTEINFOW sei{ sizeof(sei) };
|
||||
sei.fMask = { SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_NO_UI };
|
||||
sei.lpFile = L"modules\\Espresso\\PowerToys.Espresso.exe";
|
||||
sei.nShow = SW_SHOWNORMAL;
|
||||
sei.lpParameters = executable_args.data();
|
||||
if (!ShellExecuteExW(&sei))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
std::wstring message = L"Espresso failed to start with error = ";
|
||||
message += std::to_wstring(error);
|
||||
Logger::error(message);
|
||||
}
|
||||
|
||||
m_hProcess = sei.hProcess;
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Espresso()
|
||||
{
|
||||
app_name = GET_RESOURCE_STRING(IDS_ESPRESSO_NAME);
|
||||
app_key = EspressoConstants::ModuleKey;
|
||||
std::filesystem::path logFilePath(PTSettingsHelper::get_module_save_folder_location(this->app_key));
|
||||
logFilePath.append(LogSettings::espressoLogPath);
|
||||
Logger::init(LogSettings::launcherLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location());
|
||||
Logger::info("Launcher object is constructing");
|
||||
};
|
||||
|
||||
// Destroy the powertoy and free memory
|
||||
virtual void destroy() override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
// Return the display name of the powertoy, this will be cached by the runner
|
||||
virtual const wchar_t* get_name() override
|
||||
{
|
||||
return MODULE_NAME;
|
||||
}
|
||||
|
||||
// Return JSON with the configuration options.
|
||||
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
|
||||
{
|
||||
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||
|
||||
// Create a Settings object.
|
||||
PowerToysSettings::Settings settings(hinstance, get_name());
|
||||
settings.set_description(MODULE_DESC);
|
||||
|
||||
return settings.serialize_to_buffer(buffer, buffer_size);
|
||||
}
|
||||
|
||||
// Return the non localized key of the powertoy, this will be cached by the runner
|
||||
virtual const wchar_t* get_key() override
|
||||
{
|
||||
return app_key.c_str();
|
||||
}
|
||||
|
||||
// Called by the runner to pass the updated settings values as a serialized JSON.
|
||||
virtual void set_config(const wchar_t* config) override
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse the input JSON string.
|
||||
PowerToysSettings::PowerToyValues values =
|
||||
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
|
||||
|
||||
// If you don't need to do any custom processing of the settings, proceed
|
||||
// to persists the values calling:
|
||||
values.save_to_settings_file();
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
// Improper JSON.
|
||||
}
|
||||
}
|
||||
|
||||
virtual void enable()
|
||||
{
|
||||
ResetEvent(send_telemetry_event);
|
||||
ResetEvent(m_hInvokeEvent);
|
||||
launch_process();
|
||||
m_enabled = true;
|
||||
};
|
||||
|
||||
virtual void disable()
|
||||
{
|
||||
if (m_enabled)
|
||||
{
|
||||
ResetEvent(send_telemetry_event);
|
||||
ResetEvent(m_hInvokeEvent);
|
||||
TerminateProcess(m_hProcess, 1);
|
||||
}
|
||||
|
||||
m_enabled = false;
|
||||
}
|
||||
|
||||
// Returns if the powertoys is enabled
|
||||
virtual bool is_enabled() override
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new Espresso();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||
</packages>
|
||||
1
src/modules/espresso/EspressoModuleInterface/pch.cpp
Normal file
1
src/modules/espresso/EspressoModuleInterface/pch.cpp
Normal file
@@ -0,0 +1 @@
|
||||
#include "pch.h"
|
||||
7
src/modules/espresso/EspressoModuleInterface/pch.h
Normal file
7
src/modules/espresso/EspressoModuleInterface/pch.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <ProjectTelemetry.h>
|
||||
#include <shellapi.h>
|
||||
#include <Shlwapi.h>
|
||||
16
src/modules/espresso/EspressoModuleInterface/resource.h
Normal file
16
src/modules/espresso/EspressoModuleInterface/resource.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Espresso.rc
|
||||
//
|
||||
#define IDS_ESPRESSO_NAME 101
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
19
src/modules/espresso/EspressoModuleInterface/trace.cpp
Normal file
19
src/modules/espresso/EspressoModuleInterface/trace.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "pch.h"
|
||||
#include "trace.h"
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
g_hProvider,
|
||||
"Microsoft.PowerToys",
|
||||
// {38e8889b-9731-53f5-e901-e8a7c1753074}
|
||||
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
|
||||
TraceLoggingOptionProjectTelemetry());
|
||||
|
||||
void Trace::RegisterProvider()
|
||||
{
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
}
|
||||
|
||||
void Trace::UnregisterProvider()
|
||||
{
|
||||
TraceLoggingUnregister(g_hProvider);
|
||||
}
|
||||
8
src/modules/espresso/EspressoModuleInterface/trace.h
Normal file
8
src/modules/espresso/EspressoModuleInterface/trace.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
static void RegisterProvider();
|
||||
static void UnregisterProvider();
|
||||
};
|
||||
Reference in New Issue
Block a user