Update Espresso managed application with proper command line parsing

This commit is contained in:
Den Delimarsky
2021-04-08 15:12:09 -07:00
parent a178ad7524
commit c141e4eec3
4 changed files with 331 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
using System;
using System.Runtime.InteropServices;
namespace Espresso.Shell.Core
{
[FlagsAttribute]
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
{
// More details about the API used: https://docs.microsoft.com/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
/// <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
{
bool stateSettingSucceeded = (SetThreadExecutionState(state) != 0);
if (stateSettingSucceeded)
{
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
public static bool SetIndefiniteKeepAwake(bool keepDisplayOn = true)
{
if (keepDisplayOn)
{
return SetAwakeState(EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_CONTINUOUS);
}
else
{
return SetAwakeState(EXECUTION_STATE.ES_CONTINUOUS);
}
}
public static bool SetTimedKeepAwake(int seconds, bool keepDisplayOn = true)
{
if (keepDisplayOn)
{
return false;
}
else
{
return false;
}
}
}
}

View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20071.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,70 @@
using Espresso.Shell.Core;
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Threading;
namespace Espresso.Shell
{
class Program
{
private static Mutex mutex = null;
private const string appName = "Espresso";
static int Main(string[] args)
{
bool instantiated;
mutex = new Mutex(true, appName, out instantiated);
if (!instantiated)
{
Console.WriteLine(appName + " is already running! Exiting the application.");
Console.ReadKey();
Environment.Exit(1);
}
Console.WriteLine("Espresso - Computer Caffeination Engine");
var rootCommand = new RootCommand
{
new Option<bool>(
aliases: new string[] {"--display-on", "-d" },
getDefaultValue: () => false,
description: "Determines whether the display should be kept awake."),
new Option<long>(
aliases: new string[] {"--time-limit", "-t" },
getDefaultValue: () => 0,
description: "Determines the interval, in seconds, during which the computer is kept awake.")
};
rootCommand.Description = appName;
rootCommand.Handler = CommandHandler.Create<bool, long>(HandleCommandLineArguments);
return rootCommand.InvokeAsync(args).Result;
}
private static void HandleCommandLineArguments(bool displayOption, long timeOption)
{
Console.WriteLine($"The value for --display-on is: {displayOption}");
Console.WriteLine($"The value for --time-limit is: {timeOption}");
if (timeOption <= 0)
{
// Indefinite keep awake.
bool success = APIHelper.SetIndefiniteKeepAwake(displayOption);
if (success)
{
Console.WriteLine($"Currently in indefinite keep awake. Display always on: {displayOption}");
}
else
{
Console.WriteLine("Could not set up the state to be indefinite keep awake.");
}
}
new ManualResetEvent(false).WaitOne();
}
}
}