最近、Web サイトのバックエンド管理システムを設計していたときに、このページを通じて Windows サーバーを再起動できないか考えたところ
、非常に一般的と思われるコードを見つけました
。コンソールや Windows フォーム プログラムなどのデスクトップ アプリケーションを作成するときに使用されますが、ASP.NET を介した呼び出しは正常に実行できますが、
数行を除いて他のコードは再起動する必要があるため、このコードを投稿しました。
新しいクラス
を作成し
、次のコードを入力します。最初は、Win API を呼び出すときに、InteropServices が不可欠です。
システムを使用する;
System.Runtime.InteropServices を使用します。
次に、一連の定数宣言があります。 protected const int SE_PRIVILEGE_ENABLED = 0x2;
protected 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 {
public int カウント;
パブリックロングLid。
public int 属性;
}
外部アンマネージ DLL の宣言: [DllImport("kernel32.dll", ExactSpelling=true)]
protected static 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(string host, string name, 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) {
LuidStructtp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 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);
ExitWindowsEx(flg, 0);
パブリック
静的無効シャットダウン() {
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 を使用して非対話的にサーバーを再起動することはできないことがわかりました。
[ DllImport("advapi32.dll", SetLastError=true, ExactSpelling=false)]
protected static extern bool InitiateSystemShutdown(文字列名、文字列メッセージ、int タイムアウト、ブール強制、ブール再起動);
パラメータの説明:
name: LAN 内の他のマシンを再起動するために使用されるマシン名。null の場合、それはローカル マシンです。
msg: 再起動メッセージ。再起動メッセージ ボックスに表示され、Windows 2003 および XP ではメッセージ ログとしても保存されます。
timeout: 0 でない場合、再起動メッセージ ボックスが表示され、タイムアウト秒後にカウントダウンが再開されます。
Force: 強制的に再起動します。アプリケーションが作業内容を保存するかどうかを尋ねるプロンプトを待つ必要はありません。サーバーの場合は true である必要があります。
reboot: 再起動ですか? false の場合は、サーバーのシャットダウン処理を実行します。
最初に記事の冒頭のメソッドに従って AdjustTokenPrivileges を呼び出して、Privilege を取得します。 ASP.NET ページ: InitiateSystemShutdown(null,null,0, true,true);
システムが再起動されます。
ここで注意すべき点は、マシンを再起動すると、ASP.NET の実行が完了する前に、システムがさまざまなプロセスを終了し始める可能性が高いということです。もちろん、ASP.NET プロセスではこれは正常です。パフォーマンスは少し不快に思えますが、
自分のマシンでしかテストに合格していないため、権限の問題について詳しく調べていないため、確信は持てません。一般的なサーバーで正常に動作するかどうかについては、
最初は権限シミュレーション、つまり web.config ファイルの system.web セクションに <identity impersonate="true" と記述することで解決できるとしか考えていませんでした。 userName=”Administrator”,========ですが、未確認ですので、時間がある時に試してみます。 web.config はあまり安全ではないため、ここでは DPAPI を使用する必要があるかもしれませんが、これは少し突飛な話なので、最初はここでやめましょう。