mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-12-13 19:19:23 +08:00
Making sure the app can run well without a console window
Only applicable when a PID is specified.
This commit is contained in:
parent
95bac54c0e
commit
ff486e5a61
@ -3,12 +3,15 @@
|
||||
// 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;
|
||||
|
||||
#pragma warning disable SA1116 // Split parameters should start on line after declaration
|
||||
|
||||
namespace Espresso.Shell.Core
|
||||
{
|
||||
[Flags]
|
||||
@ -27,6 +30,11 @@ namespace Espresso.Shell.Core
|
||||
public class APIHelper
|
||||
{
|
||||
private const string BuildRegistryLocation = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
|
||||
public const int StdOutputHandle = -11;
|
||||
public const int StdInputHandle = -10;
|
||||
public const int StdErrorHandle = -12;
|
||||
public const uint GenericWrite = 0x40000000;
|
||||
public const uint GenericRead = 0x80000000;
|
||||
|
||||
private static readonly Logger _log;
|
||||
private static CancellationTokenSource _tokenSource;
|
||||
@ -36,12 +44,45 @@ namespace Espresso.Shell.Core
|
||||
[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)]
|
||||
public static extern IntPtr GetStdHandle(int nStdHandle);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
|
||||
public 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()
|
||||
{
|
||||
AllocConsole();
|
||||
|
||||
var outputHandle = GetStdHandle(StdOutputHandle);
|
||||
var outputFilePointer = CreateFile("CONOUT$", GenericRead | GenericWrite, FileShare.Write, IntPtr.Zero, FileMode.OpenOrCreate, 0, IntPtr.Zero);
|
||||
if (outputFilePointer != outputHandle)
|
||||
{
|
||||
SetStdHandle(StdOutputHandle, outputFilePointer);
|
||||
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
|
||||
|
@ -63,45 +63,45 @@ namespace Espresso.Shell.Core
|
||||
};
|
||||
}
|
||||
|
||||
private static Action KeepDisplayOnCallback(string text)
|
||||
private static Action KeepDisplayOnCallback(string moduleName)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
// Just changing the display mode.
|
||||
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(text);
|
||||
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||
currentSettings.Properties.KeepDisplayOn.Value = !currentSettings.Properties.KeepDisplayOn.Value;
|
||||
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), text);
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
};
|
||||
}
|
||||
|
||||
private static Action<int, int> TimedKeepAwakeCallback(string text)
|
||||
private static Action<int, int> TimedKeepAwakeCallback(string moduleName)
|
||||
{
|
||||
return (hours, minutes) =>
|
||||
{
|
||||
// Set timed keep awake.
|
||||
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(text);
|
||||
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||
currentSettings.Properties.Mode = EspressoMode.TIMED;
|
||||
currentSettings.Properties.Hours.Value = hours;
|
||||
currentSettings.Properties.Minutes.Value = minutes;
|
||||
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), text);
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
};
|
||||
}
|
||||
|
||||
private static Action IndefiniteKeepAwakeCallback(string text)
|
||||
private static Action IndefiniteKeepAwakeCallback(string moduleName)
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
// Set indefinite keep awake.
|
||||
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(text);
|
||||
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||
currentSettings.Properties.Mode = EspressoMode.INDEFINITE;
|
||||
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), text);
|
||||
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
||||
};
|
||||
}
|
||||
|
||||
internal static void SetTray(string text, bool keepDisplayOn, EspressoMode mode, Action indefiniteKeepAwakeCallback, Action<int, int> timedKeepAwakeCallback, Action keepDisplayOnCallback, Action exitCallback)
|
||||
public static void SetTray(string text, bool keepDisplayOn, EspressoMode mode, Action indefiniteKeepAwakeCallback, Action<int, int> timedKeepAwakeCallback, Action keepDisplayOnCallback, Action exitCallback)
|
||||
{
|
||||
var contextMenuStrip = new ContextMenuStrip();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\Espresso</OutputPath>
|
||||
<Nullable>enable</Nullable>
|
||||
|
@ -55,10 +55,10 @@ namespace Espresso.Shell
|
||||
|
||||
var configOption = new Option<bool>(
|
||||
aliases: new[] { "--use-pt-config", "-c" },
|
||||
getDefaultValue: () => true,
|
||||
getDefaultValue: () => false,
|
||||
description: "Specifies whether Espresso will be using the PowerToys configuration file for managing the state.")
|
||||
{
|
||||
Argument = new Argument<bool>(() => true)
|
||||
Argument = new Argument<bool>(() => false)
|
||||
{
|
||||
Arity = ArgumentArity.ZeroOrOne,
|
||||
},
|
||||
@ -130,17 +130,22 @@ namespace Espresso.Shell
|
||||
|
||||
private static void HandleCommandLineArguments(bool usePtConfig, bool displayOn, long timeLimit, int pid)
|
||||
{
|
||||
if (pid == 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
#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.
|
||||
|
||||
if (usePtConfig)
|
||||
{
|
||||
// Configuration file is used, therefore we disregard any other command-line parameter
|
||||
// and instead watch for changes in the file.
|
||||
try
|
||||
@ -177,13 +182,14 @@ namespace Espresso.Shell
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timeLimit <= 0)
|
||||
var mode = timeLimit <= 0 ? EspressoMode.INDEFINITE : EspressoMode.TIMED;
|
||||
|
||||
if (mode == EspressoMode.INDEFINITE)
|
||||
{
|
||||
SetupIndefiniteKeepAwake(displayOn);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Timed keep-awake.
|
||||
SetupTimedKeepAwake(timeLimit, displayOn);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user