Recentemente, quando estava projetando um sistema de gerenciamento de backend de site, pensei se poderia reiniciar o servidor Windows por meio da página.
Pesquisei no Google e encontrei um trecho de código que parecia ser muito comum
. usado ao escrever aplicativos de desktop, como programas Console ou Windows Form. Ele pode rodar normalmente, mas a chamada através do ASP.NET não pode passar
. Mas ainda postei esse código, pois exceto por algumas linhas, os outros códigos são necessários para reiniciar o . server. Crie
uma nova classe e preencha o seguinte código:
O primeiro é o namespace. Ao chamar a API do Win, o InteropServices é indispensável:
usando o sistema;
usando System.Runtime.InteropServices;
Depois há uma série de declarações constantes: protected const int SE_PRIVILEGE_ENABLED = 0x2;
const protegido int TOKEN_QUERY = 0x8;
const protegido int TOKEN_ADJUST_PRIVILEGES = 0x20;
string const protegida SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
const protegido int EWX_LOGOFF = 0x0;
const protegido int EWX_SHUTDOWN = 0x1;
const protegido int EWX_REBOOT = 0x2;
const protegido int EWX_FORCE = 0x4;
const protegido int EWX_POWEROFF = 0x8;
const protegido int EWX_FORCEIFHUNG = 0x10;
Defina a estrutura Luid, preste atenção nos atributos: [StructLayout(LayoutKind.Sequential, Pack=1)]
estrutura protegida LuidStruct {
contagem interna pública;
público longo Luid;
público int Atributo;
}
Declaração de DLL externa não gerenciada: [DllImport("kernel32.dll", ExactSpelling=true)]
protegido estático externo IntPtr GetCurrentProcess()
;
protegido estático extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok [
DllImport("advapi32.dll", SetLastError=true)]
protegido estático extern bool LookupPrivilegeValue(string host, string name, ref long pluid
("advapi32.dll", SetLastError=true, ExactSpelling=true)]
protegido estático extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref LuidStruct newst, int len, IntPtr prev, IntPtr relen
[DllImport("user32.dll", SetLastError=true, ExactSpelling=true)]
protegido estático extern bool ExitWindowsEx(int flg, int rea);
Em sistemas operacionais de nível NT, você precisa primeiro notificar o Windows de que o sistema está prestes a desligar e obter permissão para desligar.
A seguir está a implementação de desligamento, reinicialização e logout: protected static void DoExitWindows(int flg) {
LuidStructtp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero
OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Contagem = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(nulo, SE_SHUTDOWN_NAME, ref tp.Luid);
AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
SairWindowsEx(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);
}
Neste ponto, o código de reinicialização termina. Este código pode funcionar bem em um ambiente interativo, ou seja, quando o usuário efetuou login no Windows,
mas o ASP.NET está sendo executado em um ambiente não interativo. Verifique o MSDN e encontre o ExitWindowsEx. definição de função. Encontrei esta passagem abaixo:
A função ExitWindowsEx retorna assim que inicia o processo de desligamento. O desligamento ou logoff prossegue de forma assíncrona. A função foi projetada para interromper todos os processos na sessão de logon do chamador. Portanto, se você não for o usuário interativo, a função poderá ser bem-sucedida. sem realmente desligar o computador. Se você não for o usuário interativo, use a função InitiateSystemShutdown ou InitiateSystemShutdownEx.
Então, fiquei inspirado e descobri que ExitWindowsEx não pode ser usado para reiniciar o servidor de forma não interativa
. DllImport("advapi32. dll", SetLastError=true, ExactSpelling=false)]
protegido estático extern bool InitiateSystemShutdown (nome da string, string msg, tempo limite int, força bool, reinicialização bool);
Explicação dos parâmetros:
name: nome da máquina, utilizado para reiniciar outras máquinas da LAN. Se for nulo, é a máquina local.
msg: Mensagem de reinicialização, será exibida na caixa de mensagem de reinicialização e também será salva como um log de mensagens no Windows 2003 e XP
timeout: Se não for 0, uma caixa de mensagem de reinicialização será exibida e a contagem regressiva será reiniciada após segundos de tempo limite.
forçar: forçar reinicialização, não espere o aplicativo perguntar se deseja salvar o trabalho, para o servidor, deve ser verdade
reinicialização: É uma reinicialização? Se for falso, faça o processo de desligamento. Para o servidor,
primeiro chame AdjustTokenPrivileges de acordo com o método no início do artigo para obter o privilégio e, em seguida, execute-o
.a página ASP.NET: InitiateSystemShutdown(null,null,0, true,true);
O sistema será reiniciado.
Uma coisa a mencionar aqui é que se você reiniciar a máquina, provavelmente retornará um erro de Serviço Indisponível. Isso ocorre porque o sistema começou a encerrar vários processos antes da conclusão da execução do ASP.NET. é claro que o processo ASP.NET é normal. Embora o desempenho pareça um pouco desconfortável,
além disso, como só passei no teste em minha própria máquina, não estudei detalhadamente o problema de permissão. se ele pode rodar normalmente em um servidor geral
A princípio, pensei apenas que poderia ser resolvido por simulação de permissão, ou seja, na seção system.web do arquivo web.config, escreva <identity personate="true" userName="Administrator" password="pass">, mas não foi confirmado, tentarei quando tiver tempo. web.config não é muito seguro, então você pode precisar usar DPAPI aqui, o que é um pouco rebuscado, então vamos parar por aqui primeiro.