C# 關機/重啟/注銷計算機以及關機關不掉原因整理


一、調用 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     }

三、計算機無法關機的原因

許多計算機無法進行正常關機,如下圖所示:

img

對於此現象可以按照如下步驟解決:

(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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM