C#定时关机小程序

最近因为某个原因,我想要让Windows10系统定时关机,可惜百度了一波发现不是任务计划设置就是控制台命令行代码。后来我在Wise软件官网上找到了一个定时关机的小程序——Wise Auto Shutdown(官网下载地址),真的挺好用的。但后来我发现,这些功能都很简单容易实现,于是我就想自己写一个定时关机程序。
我毫不犹豫地选择了C#作为开发语言,因为它就是为Windows系统而生的。开发工具肯定是Visual Studio家族,我用的是2017版本,里面有和过去VB一样的可视化设计界面,而且C#有微软最近发布的人工智能代码提示插件Visual Studio IntelliCode,写起来非常舒服。

  1. 实现定时关机功能

实现关机的功能还是使用控制台命令,通过运行system32下的shutdown.exe,并且给其传递不同的命令行参数,实现不同的功能,例如关机、重启、注销、休眠等。具体参数相见控制台提示信息:

用法: C:\Windows\system32\shutdown.exe [/i | /l | /s | /sg | /r | /g | /a | /p | /h | /e | /o] [/hybrid] [/soft] [/fw] [/f]
    [/m \\computer][/t xxx][/d [p|u:]xx:yy [/c "comment"]]

    没有参数   显示帮助。这与键入 /? 是一样的。
    /?         显示帮助。这与不键入任何选项是一样的。
    /i         显示图形用户界面(GUI)。
               这必须是第一个选项。
    /l         注销。这不能与 /m 或 /d 选项一起使用。
    /s         关闭计算机。
    /sg        关闭计算机。在下一次启动时,
               重启任何注册的应用程序。
    /r         完全关闭并重启计算机。
    /g         完全关闭并重新启动计算机。在重新启动系统后,
               重启任何注册的应用程序。
    /a         中止系统关闭。
               这只能在超时期间使用。
               与 /fw 结合使用,以清除任何未完成的至固件的引导。
    /p         关闭本地计算机,没有超时或警告。
               可以与 /d 和 /f 选项一起使用。
    /h         休眠本地计算机。
               可以与 /f 选项一起使用。
    /hybrid    执行计算机关闭并进行准备以快速启动。
               必须与 /s 选项一起使用。
    /fw        与关闭选项结合使用,使下次启动转到
               固件用户界面。
    /e         记录计算机意外关闭的原因。
    /o         转到高级启动选项菜单并重新启动计算机。
               必须与 /r 选项一起使用。
    /m \\computer 指定目标计算机。
    /t xxx     将关闭前的超时时间设置为 xxx 秒。
               有效范围是 0-315360000 (10 年),默认值为 30。
               如果超时时间大于 0,则默示为
               /f 参数。
    /c "comment" 有关重新启动或关闭的原因的注释。
               最多允许 512 个字符。
    /f         强制关闭正在运行的应用程序而不事先警告用户。
               如果为 /t 参数指定大于 0 的值,
               则默示为 /f 参数。
    /d [p|u:]xx:yy  提供重新启动或关闭的原因。
               p 指示重启或关闭是计划内的。
               u 指示原因是用户定义的。
               如果未指定 p 也未指定 u,则重新启动或关闭
               是计划外的。
               xx 是主要原因编号(小于 256 的正整数)。
               yy 是次要原因编号(小于 65536 的正整数)。
  1. 程序界面
    C#定时关机小程序
  2. 代码展示
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace Auto_Shutdown
{
    public partial class AutoShutdown : Form
    {
        public AutoShutdown()
        {
            InitializeComponent();
            timeChoice = TimeChoice.AFTER_TIME;
            taskChoice = TaskChoice.SHUTDOWN;
            InitTaskValues();
            timerShow.Start();
        }

        enum TimeChoice {
            SET_TIME,//指定时间
            AFTER_TIME//从现在开始
        };
        private TimeChoice timeChoice;
        enum TaskChoice {
            SHUTDOWN,//关机
            RESTART,//重启
            CANCEL,//注销
            SLEEP//休眠
        };
        private TaskChoice taskChoice;

        private Dictionary<TaskChoice, string> TaskValues;//枚举字符串键值对

        private void InitTaskValues()
        {
            TaskValues = new Dictionary<TaskChoice, string>
            {
                { TaskChoice.CANCEL, "注销" },
                { TaskChoice.RESTART, "重启" },
                { TaskChoice.SHUTDOWN, "关机" },
                { TaskChoice.SLEEP, "休眠" }
            };
        }

        private void AfterTimeMouseEnter(object sender, MouseEventArgs e)
        {
            groupBoxSetTime.Enabled = false;
            groupBoxAfterTime.Enabled = true;
            timeChoice = TimeChoice.AFTER_TIME;
        }

        private void SetTimeMouseEnter(object sender, MouseEventArgs e)
        {
            groupBoxSetTime.Enabled = true;
            groupBoxAfterTime.Enabled = false;
            timeChoice = TimeChoice.SET_TIME;
        }

        private void MinuteEquals60(object sender, EventArgs e)
        {
            if (setMinute.Value.Equals(60))
            {
                setMinute.Value = 0;
            }
        }

        private void SetShutdown(object sender, MouseEventArgs e)
        {
            taskChoice = TaskChoice.SHUTDOWN;
        }

        private void SetCancel(object sender, MouseEventArgs e)
        {
            taskChoice = TaskChoice.CANCEL;
        }

        private void SetRestart(object sender, MouseEventArgs e)
        {
            taskChoice = TaskChoice.RESTART;
        }

        private void SetSleep(object sender, MouseEventArgs e)
        {
            taskChoice = TaskChoice.SLEEP;
        }

        private void Shutdown(object sender, MouseEventArgs e)
        {
            string waitTime = GetWaitTime().ToString();
            string args = "";
            string startTime = GetStartTime().ToString("HH:mm");
            if (!GetStartTime().Date.Equals(DateTime.Now.Date))//如果日期不同
            {
                TimeSpan timeSpan = GetStartTime().Date - DateTime.Now.Date;
                if (timeSpan.Days.Equals(1))//如果时间间隔是1天
                {
                    startTime = "明天" + startTime;
                }
                else
                {
                    startTime = GetStartTime().Date.ToString("yyyy年mm月DD日") + startTime;
                }
            }
            switch (taskChoice)//判断任务类型
            {
                case TaskChoice.SHUTDOWN:
                    if (GetWaitTime() > 0)
                    {
                        MessageBox.Show("即将在" + startTime + TaskValues[TaskChoice.SHUTDOWN], "提示");
                    }
                    args = " -s -t ";
                    break;
                case TaskChoice.CANCEL:
                    if (GetWaitTime() > 0)
                    {
                        MessageBox.Show("即将在" + startTime + TaskValues[TaskChoice.CANCEL], "提示");
                        timerCancel.Interval = GetWaitTime() * 1000;
                        timerCancel.Start();
                    }
                    else
                    {
                        System.Diagnostics.Process.Start("shutdown.exe", " -l");
                        Close();
                    }
                    return;
                case TaskChoice.RESTART:
                    if (GetWaitTime() > 0)
                    {
                        MessageBox.Show("即将在" + startTime + TaskValues[TaskChoice.RESTART], "提示");
                    }
                    args = " -r -t ";
                    break;
                case TaskChoice.SLEEP:
                    if (GetWaitTime() > 0)
                    {
                        MessageBox.Show("即将在" + startTime + TaskValues[TaskChoice.SLEEP], "提示");
                        timerSleep.Interval = GetWaitTime() * 1000;
                        timerSleep.Start();
                    }
                    else
                    {
                        System.Diagnostics.Process.Start("shutdown.exe", " -h");
                        Close();
                    }
                    return;
            }
            System.Diagnostics.Process.Start("shutdown.exe", args + waitTime);
            Close();
        }

        private void CancelShutdown(object sender, MouseEventArgs e)//取消任务
        {
            System.Diagnostics.Process.Start("shutdown.exe", " -a");
            if (timerSleep.Enabled)
            {
                timerSleep.Stop();
            }
            MessageBox.Show("已成功取消任务!", "提示");
        }

        private int GetWaitTime()//获取间隔时间(秒)
        {
            int time = 0;
            switch (timeChoice)//判断设置时间类型
            {
                case TimeChoice.SET_TIME:
                    DateTime dateTime = new DateTime(
                        chooseDate.Value.Year,
                        chooseDate.Value.Month,
                        chooseDate.Value.Day,
                        chooseTime.Value.Hour,
                        chooseTime.Value.Minute,
                        0
                    );
                    TimeSpan timeSpan = dateTime - DateTime.Now;
                    time = (int)double.Parse(timeSpan.TotalSeconds.ToString());//获取时间间隔
                    break;
                case TimeChoice.AFTER_TIME:
                    time = int.Parse((setHour.Value * 3600 + setMinute.Value * 60).ToString());
                    break;
            }
            return time;
        }

        private DateTime GetStartTime()//获取开始执行的时间
        {
            DateTime time = new DateTime();
            switch (timeChoice)//判断设置时间类型
            {
                case TimeChoice.SET_TIME:
                    time = new DateTime(
                        chooseDate.Value.Year,
                        chooseDate.Value.Month,
                        chooseDate.Value.Day,
                        chooseTime.Value.Hour,
                        chooseTime.Value.Minute,
                        0
                    );
                    break;
                case TimeChoice.AFTER_TIME:
                    time = DateTime.Now;
                    time = time.AddHours(double.Parse(setHour.Value.ToString()));//将对应的小时数加上去
                    time = time.AddMinutes(double.Parse(setMinute.Value.ToString()));//将对应的分钟数加上去
                    break;
            }
            return time;
        }

        private void SleepPause(object sender, EventArgs e)//等待指定时间后休眠
        {
            System.Diagnostics.Process.Start("shutdown.exe", " -h");
            //如果不杀掉该线程,电脑开机后立马休眠!
            timerSleep.Stop();
            Close();
        }

        private void ShowCurrentTime(object sender, EventArgs e)
        {
            showTime.Text = "当前时间:" + DateTime.Now.ToString();
            //设置指定时间的下限
            chooseDate.MinDate = DateTime.Now;
            chooseTime.MinDate = DateTime.Now;
        }

        private void CancelPause(object sender, EventArgs e)//等待指定时间后注销
        {
            System.Diagnostics.Process.Start("shutdown.exe", " -l");
            timerCancel.Stop();
            Close();
        }
    }
}