mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-12-12 18:29:24 +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.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
|
||||||
|
#pragma warning disable SA1116 // Split parameters should start on line after declaration
|
||||||
|
|
||||||
namespace Espresso.Shell.Core
|
namespace Espresso.Shell.Core
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
@ -27,6 +30,11 @@ namespace Espresso.Shell.Core
|
|||||||
public class APIHelper
|
public class APIHelper
|
||||||
{
|
{
|
||||||
private const string BuildRegistryLocation = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
|
private const string BuildRegistryLocation = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion";
|
||||||
|
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 readonly Logger _log;
|
||||||
private static CancellationTokenSource _tokenSource;
|
private static CancellationTokenSource _tokenSource;
|
||||||
@ -36,12 +44,45 @@ namespace Espresso.Shell.Core
|
|||||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||||
private static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
|
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()
|
static APIHelper()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_tokenSource = new CancellationTokenSource();
|
_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>
|
/// <summary>
|
||||||
/// Sets the computer awake state using the native Win32 SetThreadExecutionState API. This
|
/// 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
|
/// 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 () =>
|
return () =>
|
||||||
{
|
{
|
||||||
// Just changing the display mode.
|
// 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;
|
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) =>
|
return (hours, minutes) =>
|
||||||
{
|
{
|
||||||
// Set timed keep awake.
|
// Set timed keep awake.
|
||||||
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(text);
|
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||||
currentSettings.Properties.Mode = EspressoMode.TIMED;
|
currentSettings.Properties.Mode = EspressoMode.TIMED;
|
||||||
currentSettings.Properties.Hours.Value = hours;
|
currentSettings.Properties.Hours.Value = hours;
|
||||||
currentSettings.Properties.Minutes.Value = minutes;
|
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 () =>
|
return () =>
|
||||||
{
|
{
|
||||||
// Set indefinite keep awake.
|
// Set indefinite keep awake.
|
||||||
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(text);
|
var currentSettings = ModuleSettings.GetSettings<EspressoSettings>(moduleName);
|
||||||
currentSettings.Properties.Mode = EspressoMode.INDEFINITE;
|
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();
|
var contextMenuStrip = new ContextMenuStrip();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Import Project="..\..\..\Version.props" />
|
<Import Project="..\..\..\Version.props" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\Espresso</OutputPath>
|
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\modules\Espresso</OutputPath>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
@ -55,10 +55,10 @@ namespace Espresso.Shell
|
|||||||
|
|
||||||
var configOption = new Option<bool>(
|
var configOption = new Option<bool>(
|
||||||
aliases: new[] { "--use-pt-config", "-c" },
|
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.")
|
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,
|
Arity = ArgumentArity.ZeroOrOne,
|
||||||
},
|
},
|
||||||
@ -130,17 +130,22 @@ namespace Espresso.Shell
|
|||||||
|
|
||||||
private static void HandleCommandLineArguments(bool usePtConfig, bool displayOn, long timeLimit, int pid)
|
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 --use-pt-config is: {usePtConfig}");
|
||||||
_log.Info($"The value for --display-on is: {displayOn}");
|
_log.Info($"The value for --display-on is: {displayOn}");
|
||||||
_log.Info($"The value for --time-limit is: {timeLimit}");
|
_log.Info($"The value for --time-limit is: {timeLimit}");
|
||||||
_log.Info($"The value for --pid is: {pid}");
|
_log.Info($"The value for --pid is: {pid}");
|
||||||
|
|
||||||
#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)
|
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.
|
||||||
|
|
||||||
// Configuration file is used, therefore we disregard any other command-line parameter
|
// Configuration file is used, therefore we disregard any other command-line parameter
|
||||||
// and instead watch for changes in the file.
|
// and instead watch for changes in the file.
|
||||||
try
|
try
|
||||||
@ -177,13 +182,14 @@ namespace Espresso.Shell
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (timeLimit <= 0)
|
var mode = timeLimit <= 0 ? EspressoMode.INDEFINITE : EspressoMode.TIMED;
|
||||||
|
|
||||||
|
if (mode == EspressoMode.INDEFINITE)
|
||||||
{
|
{
|
||||||
SetupIndefiniteKeepAwake(displayOn);
|
SetupIndefiniteKeepAwake(displayOn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Timed keep-awake.
|
|
||||||
SetupTimedKeepAwake(timeLimit, displayOn);
|
SetupTimedKeepAwake(timeLimit, displayOn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user