C# 重啟電腦的問題

來源:互聯網
上載者:User

C# 程式重啟電腦的方法很多,網上也有不少這方面的文章,不過很多網上提供的方法在某些情況下無法擷取重啟電腦的許可權導致重啟失敗。本文對這些方法做一些簡單的討論。

作者:eaglet

 

網上介紹最多的兩種方法分別是:

System.Diagnostics.Process.Start("shutdown",@"/r");

    [DllImport("user32.dll")]        static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason);        [STAThread]        static void Main(string[] args)        {            ExitWindowsEx(ExitWindows.LogOff, ShutdownReason.MajorOther & ShutdownReason.MinorOther);            //這個語句將實現電腦登出操作            }

 

這兩種方法在通常情況下工作是沒有問題的,但在某些特殊情況下,比如案頭被其它使用者鎖定時就無法重啟電腦。本人在實際工作中遇到過噹噹前螢幕被遠端控制軟體鎖定後,我做的後台守護進程試圖重啟電腦,結果用上述兩種方法都無法成功。分析原因,應該是遠端控制軟體用另外的帳號鎖定了螢幕(通常應該是windows service 或者 network service),這時守護進程用當前帳號重啟電腦就因為沒有許可權而失敗。

要解決這個問題,我們必須要給進程賦予足夠的許可權才行,於是我在調用 ExitWindowsEx 前運行了如下代碼來賦予當前進程關閉電腦許可權

 

 
        //give current process SeShutdownPrivilege
        TokPriv1Luid tp;
 
        IntPtr hproc = GetCurrentProcess();
 
        IntPtr htok = IntPtr.Zero;
 
        if (!OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))
        {
            throw new Exception("Open Process Token fail");
        }
 
        tp.Count = 1;
 
        tp.Luid = 0;
 
        tp.Attr = SE_PRIVILEGE_ENABLED;
 
        if (!LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid))
        {
            throw new Exception("Lookup Privilege Value fail");
        }
 
        if (!AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero))
        {
            throw new Exception("Adjust Token Privileges fail");
        }

上面代碼為當前進程賦予了關閉電腦的許可權。這裡需要注意的是上述代碼要執行成功同樣需要足夠的許可權,通常當前進程需要以擁有至少是系統管理員許可權的賬戶運行。如果沒有足夠許可權,需要用程式類比系統管理員許可權,類比其它帳號許可權的問題不在本文討論範圍內。

加上如上代碼後,在其他使用者鎖定機器後,重啟電腦成功。

下面給出完整代碼

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
 
public class ExitWindows
{
    #region win32 api
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
 
    private struct TokPriv1Luid
    {
 
        public int Count;
 
        public long Luid;
 
        public int Attr;
 
    }
 
    [DllImport("kernel32.dll", ExactSpelling = true)]
    private static extern IntPtr GetCurrentProcess();
 
    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
 
    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
 
    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
        ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
 
    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern bool ExitWindowsEx(int flg, int rea);
 
    #endregion
 
    private const int SE_PRIVILEGE_ENABLED = 0x00000002;
 
    private const int TOKEN_QUERY = 0x00000008;
 
    private const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
 
    private const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
 
    #region Exit Windows Flags
    private const int EWX_LOGOFF = 0x00000000;
 
    private const int EWX_SHUTDOWN = 0x00000001;
 
    private const int EWX_REBOOT = 0x00000002;
 
    private const int EWX_FORCE = 0x00000004;
 
    private const int EWX_POWEROFF = 0x00000008;
 
    private const int EWX_FORCEIFHUNG = 0x00000010;
 
    #endregion
    
    public static void DoExitWin(int flg)
    {
 
        //give current process SeShutdownPrivilege
        TokPriv1Luid tp;
 
        IntPtr hproc = GetCurrentProcess();
 
        IntPtr htok = IntPtr.Zero;
 
        if (!OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok))
        {
            throw new Exception("Open Process Token fail");
        }
 
        tp.Count = 1;
 
        tp.Luid = 0;
 
        tp.Attr = SE_PRIVILEGE_ENABLED;
 
        if (!LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid))
        {
            throw new Exception("Lookup Privilege Value fail");
        }
 
        if (!AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero))
        {
            throw new Exception("Adjust Token Privileges fail");
        }
 
        //Exit windows
        if (!ExitWindowsEx(flg, 0))
        {
            throw new Exception("Exit Windows fail");
        }
    }
 
    /// <summary>
    /// Reboot computer
    /// </summary>
    /// <param name="force">force reboot</param>
    public static void Reboot(bool force)
    {
        if (force)
        {
            DoExitWin(EWX_REBOOT | EWX_FORCE);
        }
        else
        {
            DoExitWin(EWX_REBOOT | EWX_FORCEIFHUNG);
        }
    }
 
    /// <summary>
    /// Reboot computer force if hung
    /// </summary>
    public static void Reboot()
    {
        Reboot(false);
    }
 
    /// <summary>
    /// Shut down computer
    /// </summary>
    /// <param name="force">force shut down</param>
    public static void Shutdown(bool force)
    {
        if (force)
        {
            DoExitWin(EWX_SHUTDOWN | EWX_FORCE);
        }
        else
        {
            DoExitWin(EWX_SHUTDOWN | EWX_FORCEIFHUNG);
        }
    }
 
    /// <summary>
    /// Shut down computer force if hung
    /// </summary>
    public static void Shutdown()
    {
        Shutdown(false);
    }
 
    /// <summary>
    /// Log off
    /// </summary>
    /// <param name="force">force logoff</param>
    public static void Logoff(bool force)
    {
        if (force)
        {
            DoExitWin(EWX_LOGOFF | EWX_FORCE);
        }
        else
        {
            DoExitWin(EWX_LOGOFF | EWX_FORCEIFHUNG);
        }
    }
 
    /// <summary>
    /// logoff computer force if hung
    /// </summary>
    public static void Logoff()
    {
        Logoff(false);
    }
}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.