Недавно, когда я проектировал систему управления серверной частью веб-сайта, я задумался о том, смогу ли я перезапустить сервер Windows через страницу,
которую я искал в Google, и нашел фрагмент кода, который показался мне очень распространенным
. используется при написании настольных приложений, таких как программы Console или Windows Form. Он может работать нормально, но вызов через ASP.NET не может пройти
. Но я все же опубликовал этот код, потому что, за исключением нескольких строк, для перезапуска необходимы другие коды. server. Создайте
новый класс и заполните следующий код:
Первое — это пространство имен. При вызове Win API InteropServices обязателен:
использование системы;
использование System.Runtime.InteropServices;
Затем следует ряд объявлений констант: protected const int SE_PRIVILEGE_ENABLED = 0x2;
защищенная константа int TOKEN_QUERY = 0x8;
защищенная константа int TOKEN_ADJUST_PRIVILEGES = 0x20;
защищенная константная строка SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
защищенная константа int EWX_LOGOFF = 0x0;
защищенная константа int EWX_SHUTDOWN = 0x1;
защищенная константа int EWX_REBOOT = 0x2;
защищенная константа int EWX_FORCE = 0x4;
защищенная константа int EWX_POWEROFF = 0x8;
защищенная константа int EWX_FORCEIFHUNG = 0x10;
Определите структуру Luid, обратите внимание на атрибуты: [StructLayout(LayoutKind.Sequential, Pack=1)]
защищенная структура LuidStruct {
общественный интервал Int Count;
публичный длинный Luid;
общественный интервал Attr;
}
Объявление внешней неуправляемой библиотеки 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 (строка хоста, имя строки, ссылка на длинный pluid [
DllImport («advapi32.dll», SetLastError = true, ExactSpelling = true)]
protected static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref LuidStruct news, 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). {
ЛуидСтрукттп;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero
OpenProcessToken (hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
тп.Луид = 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);
}
public static void Shutdown() {
DoExitWindows(EWX_SHUTDOWN);
}
public static void Reboot() {
DoExitWindows(EWX_REBOOT | EWX_FORCE);
}
public static void Logoff() {
DoExitWindows(EWX_LOGOFF);
}
На этом этапе код перезапуска завершается. Этот код может хорошо работать в интерактивной среде, то есть когда пользователь вошел в систему Windows,
но ASP.NET работает в неинтерактивной среде. Проверьте MSDN и найдите ExitWindowsEx. определение функции я нашел этот отрывок ниже:
Функция ExitWindowsEx завершает работу, как только она инициировала процесс завершения работы. Затем завершение работы или выход из системы выполняются асинхронно. Функция предназначена для остановки всех процессов в сеансе входа в систему вызывающего абонента. Поэтому, если вы не являетесь интерактивным пользователем, функция может завершиться успешно. без фактического выключения компьютера. Если вы не являетесь интерактивным пользователем, используйте функцию InitiateSystemShutdown или InitiateSystemShutdownEx.
Итак, я был вдохновлен и обнаружил, что ExitWindowsEx нельзя использовать для неинтерактивного перезапуска сервера. Вам необходимо заменить его на InitiateSystemShutdown:
[. DllImport("advapi32. dll", SetLastError=true, ExactSpelling=false)]
protected static extern bool InitiateSystemShutdown (имя строки, строка msg, время ожидания int, bool Force, boolперезагрузка);
Объяснение параметра:
name: имя машины, используемое для перезапуска других машин в локальной сети. Если оно равно нулю, это локальная машина.
msg: сообщение о перезагрузке будет отображаться в окне сообщения о перезагрузке, а также будет сохранено в виде журнала сообщений в Windows 2003 и XP.
таймаут: если он не равен 0, будет отображено окно сообщения о перезапуске, и обратный отсчет возобновится через несколько секунд таймаута.
Force: принудительный перезапуск, не ждите, пока приложение спросит, сохранять ли работу, для сервера это должно быть правдой
перезагрузка: это перезагрузка? Если это ложь, выполните процесс выключения сервера.
Сначала вызовите AdjustTokenPrivileges в соответствии с методом, описанным в начале статьи, а затем выполните его. страница ASP.NET: InitiateSystemShutdown(null,null,0, true,true);
Система перезагрузится.
Здесь следует упомянуть, что если вы перезапустите компьютер, он, скорее всего, вернет ошибку «Служба недоступна». Это связано с тем, что система начала завершать различные процессы до завершения выполнения ASP.NET. конечно процесс ASP.NET. Это нормально. Хотя производительность кажется немного неудобной,
кроме того, поскольку я проходил тест только на своей машине, я не изучал вопрос разрешений подробно, поэтому не могу быть уверен. сможет ли он нормально работать на общем сервере.
Сначала я думал только, что это можно решить симуляцией разрешений, то есть в разделе system.web файла web.config прописать <identity impersonate="true" userName="Администратор" пароль="пароль">, но он не подтвержден. Попробую, когда будет время. web.config не очень безопасен, поэтому вам, возможно, придется использовать здесь DPAPI, что немного надуманно, поэтому давайте сначала остановимся на этом.