Baru-baru ini, ketika saya sedang merancang sistem manajemen backend situs web, saya memikirkan apakah saya dapat me-restart server Windows melalui halaman tersebut.
Saya mencari di Google dan menemukan sepotong kode yang sepertinya sangat
umum digunakan saat menulis aplikasi desktop seperti program Console atau Windows Form. Ini dapat berjalan normal, tetapi panggilan melalui ASP.NET tidak dapat lewat
. Tapi saya tetap memposting kode ini, karena kecuali beberapa baris, kode lain diperlukan untuk memulai ulang server. Buat
kelas baru dan isi kode berikut. :
Yang pertama adalah namespace. Saat memanggil Win API, InteropServices sangat diperlukan:
menggunakan Sistem;
menggunakan System.Runtime.InteropServices;
Lalu ada serangkaian deklarasi konstan: protected const int SE_PRIVILEGE_ENABLED = 0x2;
dilindungi const int TOKEN_QUERY = 0x8;
dilindungi const int TOKEN_ADJUST_PRIVILEGES = 0x20;
string const yang dilindungi SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
dilindungi const int EWX_LOGOFF = 0x0;
dilindungi const int EWX_SHUTDOWN = 0x1;
dilindungi const int EWX_REBOOT = 0x2;
dilindungi const int EWX_FORCE = 0x4;
dilindungi const int EWX_POWEROFF = 0x8;
konstanta terlindungi int EWX_FORCEIFHUNG = 0x10;
Tentukan struktur Luid, perhatikan atributnya: [StructLayout(LayoutKind.Sequential, Pack=1)]
struct yang dilindungi LuidStruct {
Hitungan int publik;
Luid panjang publik;
publik int Attr;
}
Deklarasi DLL eksternal yang tidak dikelola: [DllImport("kernel32.dll", ExactSpelling=true)]
dilindungi statis eksternal IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", SetLastError=true)]
bool eksternal statis yang dilindungi OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
[DllImport("advapi32.dll", SetLastError=true)]
bool eksternal statis yang dilindungi LookupPrivilegeValue(string host, nama string, ref long pluid);
[DllImport("advapi32.dll", SetLastError=true, ExactSpelling=true)]
bool eksternal statis yang dilindungi AdjustTokenPrivileges(IntPtr htok, bool disall, ref LuidStruct newst, int len, IntPtr prev, IntPtr relen);
[DllImport("user32.dll", SetLastError=true, ExactSpelling=true)]
bool eksternal statis yang dilindungi ExitWindowsEx(int flg, int rea);
Pada sistem operasi level NT, Anda harus terlebih dahulu memberi tahu Windows bahwa sistem akan dimatikan, dan mendapatkan izin untuk mematikan.
Berikut ini adalah implementasi shutdown, restart, dan logout: protected static void DoExitWindows(int flg) {
Struktur Luidtp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Hitungan = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
Keluar dari WindowsEx(flg, 0);
}
Shutdown kekosongan statis publik() {
LakukanKeluar dari Windows(EWX_SHUTDOWN);
}
public static void Reboot() {
DoExitWindows(EWX_REBOOT | EWX_FORCE);
}
public static void Logoff() {
LakukanKeluar dari Windows(EWX_LOGOFF);
}
Pada titik ini, kode restart berakhir. Kode ini dapat bekerja dengan baik di lingkungan interaktif, yaitu ketika pengguna telah masuk ke Windows,
tetapi ASP.NET berjalan di lingkungan non-interaktif definisi fungsi. Saya menemukan bagian ini di bawah:
Fungsi ExitWindowsEx kembali segera setelah memulai proses pematian. Pematian atau logoff kemudian dilanjutkan secara asinkron. Fungsi ini dirancang untuk menghentikan semua proses dalam sesi masuk pemanggil. Oleh karena itu, jika Anda bukan pengguna interaktif, fungsi tersebut dapat berhasil tanpa benar-benar mematikan komputer. Jika Anda bukan pengguna interaktif, gunakan fungsi InitiateSystemShutdown atau InitiateSystemShutdownEx.
Jadi saya terinspirasi dan menemukan bahwa ExitWindowsEx tidak dapat digunakan untuk me-restart server secara non-interaktif
. DllImport("advapi32.dll", SetLastError=benar, ExactSpelling=false)]
bool eksternal statis yang dilindungi InitiateSystemShutdown (nama string, pesan string, batas waktu int, bool force, bool reboot);
Penjelasan parameter:
name: nama mesin, digunakan untuk me-restart mesin lain di LAN. Jika null, itu adalah mesin lokal.
pesan: Pesan restart, akan ditampilkan pada kotak pesan restart, dan juga akan disimpan sebagai log pesan di Windows 2003 dan XP
batas waktu: Jika bukan 0, kotak pesan mulai ulang akan ditampilkan dan hitungan mundur akan dimulai ulang setelah batas waktu beberapa detik.
force: force restart, jangan menunggu aplikasi menanyakan apakah akan menyimpan pekerjaan, untuk server, itu harus benar
reboot: Apakah itu reboot? Jika salah, maka lakukan proses shutdown. Untuk servernya harus benar.
Panggil dulu AdjustTokenPrivileges sesuai cara di awal artikel untuk mendapatkan Privilege, lalu jalankan di halaman ASP.NET: InitiateSystemShutdown(null,null,0, true,true);
Sistem akan restart.
Satu hal yang perlu disebutkan di sini adalah jika Anda me-restart mesin, kemungkinan besar akan mengembalikan kesalahan Service Unavailable. Hal ini karena sistem telah mulai mengakhiri berbagai proses sebelum eksekusi ASP.NET selesai, termasuk tentu saja proses ASP.NET. Ini normal. Meskipun kinerjanya tampak agak tidak nyaman,
selain itu, karena saya hanya lulus tes di mesin saya sendiri, saya belum mempelajari masalah izin secara detail, jadi saya tidak bisa memastikannya. apakah bisa berjalan normal di server umum.Pada
awalnya saya hanya berpikir itu bisa diselesaikan dengan simulasi izin, yaitu di bagian system.web pada file web.config, tulis <identity impersonate="true" userName="Administrator" password="pass">, tetapi belum dikonfirmasi. Saya akan mencobanya ketika saya punya waktu. web.config tidak terlalu aman, jadi Anda mungkin perlu menggunakan DPAPI di sini, yang agak tidak masuk akal, jadi mari kita berhenti di sini dulu.