一、调用 shutdown.exe 执行操作

调用 shutdown.exe 执行计算机关机、重启、注销操作,还可以设置多长时间后执行操作,代码如下:

 1         /// <summary>
 2         /// 控制 PC 开机、重启
 3         /// </summary>
 4         /// <param name="cmd">0:关机;1:重启;2:注销</param>
 5         public static void ShutdownComputer(int cmd)
 6         {
 7             try
 8             {
 9
10                 if (cmd == 0)//5秒后关机
11                 {
12                     System.Diagnostics.Process.Start("shutdown.exe", "/s /t 5");
13                 }
14                 else if (cmd == 1)//5秒后重启
15                 {
16                     System.Diagnostics.Process.Start("shutdown.exe", "/r /t 5");
17                 }
18                 else if (cmd == 2)//注销
19                 {
20                     System.Diagnostics.Process.Start("shutdown.exe", "/l");
21                 }
22             }
23             catch (Exception ex)
24             {
25                 Console.WriteLine($"启动电脑关机程序异常", ex);
26             }
27         }

二、使用 WinAPI 执行操作

使用 WinAPI 直接调用关机、重启、注销操作,更为快速稳定,具体代码如下:

 1  class SystemUtil
 2     {
 3         [StructLayout(LayoutKind.Sequential, Pack = 1)]
 4         internal struct TokPriv1Luid
 5         {
 6             public int Count;
 7             public long Luid;
 8             public int Attr;
 9         }
10
11         [DllImport("kernel32.dll", ExactSpelling = true)]
12         private static extern IntPtr GetCurrentProcess();
13
14         [System.Runtime.InteropServices.DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
15         private static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
16
17         [DllImport("advapi32.dll", SetLastError = true)]
18         private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
19
20         [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
21         private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
22
23         [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
24         private static extern bool ExitWindowsEx(int flg, int rea);
25
26         private const int SE_PRIVILEGE_ENABLED = 0x00000002;
27         private const int TOKEN_QUERY = 0x00000008;
28         private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
29         private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
30         private const int EWX_LOGOFF = 0x00000000;
31         private const int EWX_SHUTDOWN = 0x00000001;
32         private const int EWX_REBOOT = 0x00000002;
33         private const int EWX_FORCE = 0x00000004;
34         private const int EWX_POWEROFF = 0x00000008;
35         private const int EWX_FORCEIFHUNG = 0x00000010;
36
37         private static void DoExitWin(int flg)
38         {
39             IntPtr hproc = GetCurrentProcess();
40             IntPtr htok = IntPtr.Zero;
41             TokPriv1Luid tpl = new TokPriv1Luid()
42             {
43                 Count = 1,
44                 Luid = 0,
45                 Attr = SE_PRIVILEGE_ENABLED,
46             };
47             OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
48             LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tpl.Luid);
49             AdjustTokenPrivileges(htok, false, ref tpl, 0, IntPtr.Zero, IntPtr.Zero);
50             ExitWindowsEx(flg, 0);
51         }
52
53         /// <summary>
54         /// 控制 PC 开机、重启
55         /// </summary>
56         /// <param name="cmd">0:关机;1:重启;2:注销</param>
57         public static void ShutdownComputer(int cmd)
58         {
59             switch (cmd)
60             {
61                 case 0:
62                     DoExitWin(EWX_FORCE | EWX_POWEROFF);
63                     break;
64                 case 1:
65                     DoExitWin(EWX_FORCE | EWX_REBOOT);
66                     break;
67                 case 2:
68                     DoExitWin(EWX_FORCE | EWX_LOGOFF);
69                     break;
70             }
71         }
72
73     }

三、计算机无法关机的原因

 许多计算机无法进行正常关机,如下图所示:

C# 关机/重启/注销计算机以及关机关不掉原因整理-LMLPHP

 对于此现象可以按照如下步骤解决:

(1)使用杀毒软件确定是否有病毒病毒会阻止关机程序的执行,破坏注册表中的相关选项或系统文件,杀毒将包含病毒的系统文件清除的问题。

(2)设置注册表 shutdownwithoutlogon 的数值为1。点开始——在运行框中输入regedit,按回车键;依次展开HKEY-LOCAL-MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\System,双击右侧的shutdownwithoutlogon,数值数据输入1,点确定。

(3)禁用阻止关机功能。开始”→“运行”,在“运行”对话框中输入“gpedit.msc”,然后点击“确定”按钮。在“组策略”窗口中,双击“管理模板”→“任务 栏和「开始」菜单”,然后双击右侧的“删除和阻止访问‘关机’命令”。在“删除和阻止访问‘关机’命令属性”窗口中,点击“设置”选项卡,选择“已禁 用”,然后点击“确定”按钮。

(4)关闭关机自检。开始”→“运行”,在“运行”对话框中输入“gpedit.msc”,然后点击“确定”按钮。在“组策略”窗口中,双击“管理模板”→“任务 栏和「开始」菜单”,然后双击右侧的“关闭会阻止或取消关机的应用程序的自动终止功能”,双击弹出属性对话框,在这里将默认的“未配置”更改为“已启用”,确认之后即可生效。 这样一来,相关的应用程序就不会在关机期间自动终止,可加快关机速度,不过也有可能导致应用程序的数据丢失。https://www.kafan.cn/edu/85550102.html

(5)禁用快速关机。快速关机是Windows 98中的新增功能,可以大大减少关机时间。但是,该功能与某些硬件不兼容,假如计算机中安装了这些硬件,可能会导致计算机休止响应。可禁用快速关机,先单击“开始”→“运行”,在“打开”框中键入“Msconfig”,然后单击“确定”(见图1)。单击“高级”→“禁用快速关机”,单击“确定”,再次单击“确定”。系统提示重新启动计算机,可重新启动。假如计算性能正常关机,则快速关机功能可能与计算机上所安装的一个或多个硬件设备不兼容。https://www.cixi8.com/yulu/103552.html

(6)检查一下声音文件是否正常。如果你的win7系统在关机的时候设置了退出声音的话,那么一旦声音文件发生损坏的时候,就会导致计算机无法关闭,所以要检查一下系统的声音文件是否正常。打开控制面板,然后再控制面板中找到并双击“声音和多媒体”项;在打开界面中,切换到“声音”选项卡下,然后选中“声音事件”中的“退出Windows”选项,接着再将“名称”设置为无,这样就能取消关机时的声音了;然后尝试关闭计算机,如果在取消声音之后,能够正常关闭的话就说明是声音文件造成的,那如果是这个原因的话就要重新安装一下声音文件的应用程序,或者也可以从备份文件中进行恢复,简单的方法是直接将关机声音取消即可。http://www.win7zhijia.cn/jiaocheng/win7_1296.html

(7)关机前提前关闭可能导致系统无法关机的进程,例如“rundll32”类进程,可加速关机速度:https://jingyan.baidu.com/article/cd4c2979269130756e6e60ee.html

01-22 01:54