최근에 웹사이트 백엔드 관리 시스템을 설계할 때 페이지를 통해 Windows 서버를 다시 시작할 수 있는지 고민하다가
Google에서 검색해 보니 매우 흔해 보이는 코드를 발견했습니다
. 콘솔이나 Windows Form 프로그램과 같은 데스크톱 응용 프로그램을 작성할 때 사용됩니다. 정상적으로 실행될 수 있지만 ASP.NET을 통한 호출은
.
새 클래스를만들고
다음 코드를 입력합니다.
첫 번째는 Win API를 호출할 때 필수적입니다.
시스템 사용;
System.Runtime.InteropServices 사용;
그런 다음 일련의 상수 선언이 있습니다. protected const int SE_PRIVILEGE_ENABLED = 0x2;
보호된 const int TOKEN_QUERY = 0x8;
protected const int TOKEN_ADJUST_PRIVILEGES = 0x20;
protected const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
protected const int EWX_LOGOFF = 0x0;
protected const int EWX_SHUTDOWN = 0x1;
protected const int EWX_REBOOT = 0x2;
protected const int EWX_FORCE = 0x4;
protected const int EWX_POWEROFF = 0x8;
protected const int EWX_FORCEIFHUNG = 0x10;
Luid 구조를 정의하고 속성에 주의하세요: [StructLayout(LayoutKind.Sequential, Pack=1)]
보호된 구조체 LuidStruct {
공개 정수 개수;
공개 긴 Luid;
공개 int 속성;
}
관리되지 않는 외부 DLL 선언: [DllImport("kernel32.dll", ExactSpelling=true)]
보호된 정적 extern IntPtr GetCurrentProcess()
[DllImport("advapi32.dll", SetLastError=true)]
protected static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok)
[DllImport("advapi32.dll", SetLastError=true)]
protected static extern bool LookupPrivilegeValue(문자열 호스트, 문자열 이름, ref long pluid)
[DllImport("advapi32.dll", SetLastError=true, ExactSpelling=true)]
protected static extern bool adjustTokenPrivileges(IntPtr htok, bool disall, ref LuidStruct newst, int len, IntPtr prev, IntPtr relen)
[DllImport("user32.dll", SetLastError=true, ExactSpelling=true)]
protected static extern bool ExitWindowsEx(int flg, int rea);
NT 수준 운영 체제에서는 먼저 시스템이 종료되려고 한다는 사실을 Windows에 알리고 종료 권한을 얻어야 합니다.
다음은 종료, 다시 시작 및 로그아웃의 구현입니다. protected static void DoExitWindows(int flg) {
LuidStructp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.루이드 = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
adjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
ExitWindowsEx(flg, 0);
}
공개 정적 무효 종료() {
DoExitWindows(EWX_SHUTDOWN);
}
공개 정적 무효 재부팅() {
DoExitWindows(EWX_REBOOT | EWX_FORCE);
}
공개 정적 무효 로그오프() {
DoExitWindows(EWX_LOGOFF);
}
이 시점에서 다시 시작 코드가 종료됩니다. 이 코드는 대화형 환경, 즉 사용자가 Windows에 로그인했지만
ASP.NET이 비대화형 환경에서 실행되고 있는 경우 MSDN을 확인하고 ExitWindowsEx를 찾으면 잘 작동합니다. 함수 정의. 아래에서 이 구절을 찾았습니다.
ExitWindowsEx 함수는 종료 프로세스를 시작하자마자 반환하고 비동기적으로 진행합니다. 따라서 호출자의 로그온 세션에서 모든 프로세스를 중지하도록 설계되었습니다. 실제로 컴퓨터를 종료하지 않고 대화형 사용자가 아닌 경우 InitiateSystemShutdown 또는 InitiateSystemShutdownEx 함수를 사용하십시오.
그래서
저는 ExitWindowsEx를 사용하여 비대화형으로 서버를 다시 시작할 수 없다는 것을 알게 되었습니다.
DllImport("advapi32.dll", SetLastError=true, ExactSpelling=false)]
protected static extern bool InitiateSystemShutdown(문자열 이름, 문자열 msg, int 시간 초과, bool force, bool 재부팅);
매개변수 설명:
name: LAN의 다른 시스템을 다시 시작하는 데 사용되는 시스템 이름입니다. null인 경우 로컬 시스템입니다.
msg: 재시작 메시지는 재시작 메시지 상자에 표시되며, Windows 2003 및 XP에서는 메시지 로그로도 저장됩니다.
timeout: 0이 아닌 경우 재시작 메시지 상자가 표시되고 타임아웃 초 후에 카운트다운이 다시 시작됩니다.
force: 강제로 다시 시작합니다. 응용 프로그램이 작업을 저장할지 여부를 묻는 메시지를 표시할 때까지 기다리지 마십시오. 서버의 경우 true여야 합니다.
재부팅: 재부팅인가요? false인 경우 종료 프로세스를 수행합니다. 서버의 경우
먼저 해당 항목의 시작 부분에 있는 메서드에 따라 adjustTokenPrivileges를 호출한 후 실행합니다
.ASP.NET 페이지: InitiateSystemShutdown(null,null,0, true,true);
시작
하면 서비스를 사용할 수 없음 오류가 반환될 가능성이 높다는 것입니다. 이는 ASP.NET 실행이 완료되기 전에 시스템이 다양한 프로세스를 종료하기 시작했기 때문입니다. 물론 ASP.NET 프로세스에서는 정상입니다. 성능이 다소 불편한 것 같지만,
게다가 제 컴퓨터에서만 테스트를 통과했기 때문에 권한 문제에 대해 자세히 연구하지 않았기 때문에 확신할 수 없습니다. 일반 서버에서 정상적으로 실행이 가능한지
처음에는 권한 시뮬레이션, 즉 web.config 파일의 system.web 섹션에 <identity impersonate="true"라고 적으면 해결될 거라 생각했습니다. userName="Administrator"password="pass">, 아직 확인되지 않았습니다. 시간이 나면 시도해 보겠습니다. web.config는 그다지 안전하지 않기 때문에 여기에서는 DPAPI를 사용해야 할 수도 있는데, 이는 다소 무리가 있으므로 먼저 여기서 멈추겠습니다.