feat(app): 初始化自动关机工具首个版本
实现基于 WPF 的 AutoShutdown 主界面,支持关机、重启、睡眠、休眠、唤醒、锁屏和注销等电源任务。 支持指定时间和倒计时计划、执行前提醒、系统关机撤销、Windows 唤醒任务、托盘运行、自定义图标以及 OmniNotify 通知适配。 修复关闭到托盘时的运行提醒,并支持单击托盘图标打开或收起主界面。 补充 README、发布配置和 win-x64 Release 输出要求。 Release: win-x64
This commit is contained in:
95
Services/PowerService.cs
Normal file
95
Services/PowerService.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using AutoShutdown.Models;
|
||||
|
||||
namespace AutoShutdown.Services;
|
||||
|
||||
internal sealed class PowerService
|
||||
{
|
||||
[DllImport("PowrProf.dll", SetLastError = true)]
|
||||
private static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern bool LockWorkStation();
|
||||
|
||||
public void Execute(PowerAction action, int delaySeconds, bool forceApps)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case PowerAction.Shutdown:
|
||||
RunShutdownCommand($"/s /t {Math.Max(0, delaySeconds)}{ForceFlag(forceApps)}");
|
||||
break;
|
||||
case PowerAction.Restart:
|
||||
RunShutdownCommand($"/r /t {Math.Max(0, delaySeconds)}{ForceFlag(forceApps)}");
|
||||
break;
|
||||
case PowerAction.LogOff:
|
||||
if (delaySeconds > 0)
|
||||
{
|
||||
using var timer = new System.Threading.Timer(_ => RunShutdownCommand($"/l{ForceFlag(forceApps)}"), null, TimeSpan.FromSeconds(delaySeconds), Timeout.InfiniteTimeSpan);
|
||||
Thread.Sleep(TimeSpan.FromSeconds(delaySeconds + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
RunShutdownCommand($"/l{ForceFlag(forceApps)}");
|
||||
}
|
||||
break;
|
||||
case PowerAction.Lock:
|
||||
DelayThen(delaySeconds, () => LockWorkStation());
|
||||
break;
|
||||
case PowerAction.Sleep:
|
||||
DelayThen(delaySeconds, () => SetSuspendState(false, forceApps, false));
|
||||
break;
|
||||
case PowerAction.Hibernate:
|
||||
DelayThen(delaySeconds, () => SetSuspendState(true, forceApps, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool CancelShutdown()
|
||||
{
|
||||
var result = RunProcess("shutdown.exe", "/a", showWindow: false);
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
private static string ForceFlag(bool forceApps) => forceApps ? " /f" : string.Empty;
|
||||
|
||||
private static void DelayThen(int delaySeconds, Action action)
|
||||
{
|
||||
if (delaySeconds > 0)
|
||||
{
|
||||
Task.Delay(TimeSpan.FromSeconds(delaySeconds)).ContinueWith(_ => action(), TaskScheduler.Default);
|
||||
return;
|
||||
}
|
||||
|
||||
action();
|
||||
}
|
||||
|
||||
private static void RunShutdownCommand(string arguments)
|
||||
{
|
||||
var code = RunProcess("shutdown.exe", arguments, showWindow: false);
|
||||
if (code != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"shutdown.exe 执行失败,退出码 {code}。");
|
||||
}
|
||||
}
|
||||
|
||||
private static int RunProcess(string fileName, string arguments, bool showWindow)
|
||||
{
|
||||
using var process = Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = fileName,
|
||||
Arguments = arguments,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = !showWindow,
|
||||
WindowStyle = showWindow ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden
|
||||
});
|
||||
|
||||
if (process is null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
return process.ExitCode;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user