实现基于 WPF 的 AutoShutdown 主界面,支持关机、重启、睡眠、休眠、唤醒、锁屏和注销等电源任务。 支持指定时间和倒计时计划、执行前提醒、系统关机撤销、Windows 唤醒任务、托盘运行、自定义图标以及 OmniNotify 通知适配。 修复关闭到托盘时的运行提醒,并支持单击托盘图标打开或收起主界面。 补充 README、发布配置和 win-x64 Release 输出要求。 Release: win-x64
96 lines
3.1 KiB
C#
96 lines
3.1 KiB
C#
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;
|
|
}
|
|
}
|