C# 컴퓨터 재부팅 문제

19658 단어 컴퓨터
C#프로그램이 컴퓨터를 재부팅하는 방법이 매우 많고 인터넷에도 이런 방면의 글이 적지 않다. 그러나 많은 인터넷에서 제공한 방법은 어떤 상황에서 컴퓨터를 재부팅할 수 있는 권한을 얻지 못해 재부팅에 실패했다.본고는 이 방법들에 대해 간단한 토론을 한다.
작성자: eaglet
 
온라인에서 가장 많이 소개되는 두 가지 방법은 다음과 같습니다.
System.Diagnostics.Process.Start("shutdown",@"/r");

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
    [DllImport("user32.dll")]

        static extern bool ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason);



        [STAThread]

        static void Main(string[] args)

        {

            ExitWindowsEx(ExitWindows.LogOff, ShutdownReason.MajorOther & ShutdownReason.MinorOther);

            //                 

         }

 
이 두 가지 방법은 일반적인 상황에서는 문제가 없지만, 예를 들어 데스크톱이 다른 사용자에게 잠겼을 때 컴퓨터를 다시 시작할 수 없다.본인은 실제 업무에서 현재 화면이 원격 제어 소프트웨어에 잠긴 후에 백엔드 수호 프로세스가 컴퓨터를 다시 시작하려고 시도했지만 상술한 두 가지 방법으로는 성공하지 못했다.분석 원인은 원격 제어 소프트웨어가 다른 계정으로 화면을 잠갔기 때문(일반적으로 윈도우즈 서비스나network 서비스)이다. 이때 수호 프로세스가 현재 계정으로 컴퓨터를 다시 시작하는 것은 권한이 없기 때문에 실패한 것이다.
이 문제를 해결하려면 프로세스에 충분한 권한을 부여해야 합니다. 그래서 저는 ExitWindowsEx를 호출하기 전에 현재 프로세스에 컴퓨터를 닫을 수 있는 권한을 부여하기 위해 아래 코드를 실행했습니다.
  .csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
 
        //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");
        }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
위 코드는 현재 프로세스에 컴퓨터를 닫을 수 있는 권한을 부여합니다.여기서 주의해야 할 것은 상술한 코드가 실행되기 위해서는 충분한 권한이 필요합니다. 보통 현재 프로세스는 최소한 시스템 관리자 권한이 있는 계정으로 실행되어야 합니다.만약 충분한 권한이 없다면 프로그램으로 시스템 관리자 권한을 모의해야 한다. 다른 계정 권한을 모의하는 문제는 본고에서 논의한 범위에 있지 않다.
상기 코드를 더한 후 다른 사용자가 기계를 잠근 후에 컴퓨터를 다시 시작하는 데 성공했다.
다음은 전체 코드를 제시합니다
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);
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

좋은 웹페이지 즐겨찾기