Windowsサービス(サーバー2003)が自動的に再起動できるようにするには、.NETで堅牢なコードを作成する必要があります。これを行うための最良の方法は何ですか?それを行うための.NETAPIはありますか?
17 に答える
失敗後にサービスを再起動するように設定します (コントロール パネルでサービスをダブルクリックし、それらのタブを調べてください。サービスの名前を忘れてしまいました)。次に、サービスを再起動する必要があるときはいつでも、呼び出しEnvironment.Exit(1)
(またはゼロ以外の戻り値) を行うだけで、OS がサービスを再起動します。
Dim proc As New Process()
Dim psi As New ProcessStartInfo()
psi.CreateNoWindow = True
psi.FileName = "cmd.exe"
psi.Arguments = "/C net stop YOURSERVICENAMEHERE && net start YOURSERVICENAMEHERE"
psi.LoadUserProfile = False
psi.UseShellExecute = False
psi.WindowStyle = ProcessWindowStyle.Hidden
proc.StartInfo = psi
proc.Start()
サービスが実行されているユーザーアカウントに、サービスを停止および再起動する権限があるかどうかを確認することはできません。
cmd.exe
自分自身を再起動する Windows を使用してサブプロセスを作成できます。
Process process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
process.Start();
それは、なぜそれ自体を再起動したいのかによって異なります。
サービス自体を定期的にクリーンアップする方法を探しているだけの場合は、定期的にパージ ルーチンを発生させるタイマーをサービスで実行することができます。
失敗時に再起動する方法を探している場合は、セットアップ時にサービス ホスト自体がその機能を提供できます。
では、なぜサーバーを再起動する必要があるのでしょうか。何を達成しようとしていますか?
自己完結型のサービスではできないと思います(Restartを呼び出すと、サービスが停止し、Restartコマンドが中断され、再開されることはありません)。2番目の.exe(ServiceManagerクラスを使用するコンソールアプリ)を追加できる場合は、スタンドアロンの.exeを起動して、サービスを再起動してから終了することができます。
考え直してみると、サービスを開始してからそれ自体を停止させるために、サービスにスケジュールされたタスクを登録させることができます(たとえば、コマンドライン'at'コマンドを使用)。それはおそらくうまくいくでしょう。
バッチ ファイルまたは EXE へのシェル アウトの問題は、サービスが外部アプリを実行するために必要なアクセス許可を持っている場合と持っていない場合があることです。
私が見つけた最もクリーンな方法は、サービス コントロール マネージャーのエントリ ポイントである OnStop() メソッドを使用することです。その後、すべてのクリーンアップ コードが実行され、停止コードが機能していると仮定して、ソケットやその他のプロセスがハングすることはありません。
これを行うには、終了する前に、OnStop メソッドにエラー コードで終了するように指示するフラグを設定する必要があります。その後、SCM は、サービスを再起動する必要があることを認識します。このフラグがないと、SCM から手動でサービスを停止することはできません。これは、エラー時にサービスを再起動するように設定していることも前提としています。
ここに私の停止コードがあります:
...
bool ABORT;
protected override void OnStop()
{
Logger.log("Stopping service");
WorkThreadRun = false;
WorkThread.Join();
Logger.stop();
// if there was a problem, set an exit error code
// so the service manager will restart this
if(ABORT)Environment.Exit(1);
}
サービスで問題が発生し、再起動が必要になった場合は、SCM からサービスを停止するスレッドを起動します。これにより、サービスはそれ自体をクリーンアップできます。
...
if(NeedToRestart)
{
ABORT = true;
new Thread(RestartThread).Start();
}
void RestartThread()
{
ServiceController sc = new ServiceController(ServiceName);
try
{
sc.Stop();
}
catch (Exception) { }
}
質問に対する最初の回答は、最も単純な解決策です。「Environment.Exit(1)」これをWindows Server 2008 R2で使用していますが、完全に機能します。サービスは自動的に停止し、O / Sは1分間待機してから、再起動します。
Windows スケジューラを使用して、サービスの再起動をスケジュールします。問題は、自分自身を再起動することはできませんが、自分自身を停止することはできます. (基本的に、あなたが座っているブランチを切り落としたのです...私の類推が得られれば)それを行うには別のプロセスが必要です。Windows スケジューラは適切なものです。サービスを再起動する 1 回限りのタスクを (サービス自体からでも) すぐに実行するようにスケジュールします。
それ以外の場合は、それを行う「シェパディング」プロセスを作成する必要があります。
私はそれができないと思います。サービスが「停止」されると、完全にアンロードされます。
ええと、OK、私が思う方法は常にあります。たとえば、デタッチされたプロセスを作成してサービスを停止し、再起動してから終了することができます。
ただ合格:そして私はいくつかの追加情報を追加すると思いました...
例外をスローすることもできます。これにより、Windowsサービスが自動的に閉じられ、自動再起動オプションが開始されます。これに関する唯一の問題は、PCに開発環境がある場合、JITが開始しようとすることです。そして、debug Y/Nというプロンプトが表示されます。「いいえ」と言うと、閉じてから、正しく再起動します。(JITのないPCでは、すべてが機能します)。制御する理由は、このJITがWin 7の新機能であり(XPなどで正常に動作していた)、JITを無効にする方法を見つけようとしているためです。Environment.Exitメソッドを試してみてください。それも機能します。
クリスチャン:イギリス、ブリストル
アプリケーション コードをホストする別の appdomain を作成します。再起動が必要な場合は、プロセス (Windows サービス) ではなく、アプリドメインをアンロードして再ロードできます。これは、IIS アプリ プールのしくみです。asp.net アプリを直接実行せず、別の appdmain を使用します。
NT サービスをアプリケーションのラッパーとして利用する方がよい場合があります。NT サービスが開始されると、アプリケーションは「アイドル」モードで開始され、コマンドが開始される (または自動的に開始するように設定される) のを待機します。
車を考えてみてください。始動するとアイドル状態になり、コマンドが前進または後退するのを待ちます。これにより、アプリケーションの公開方法を選択できるため、リモート管理が向上するなど、他の利点も得られます。
最も簡単な方法は、次のバッチファイルを作成することです。
ネットストップネットスタート
希望の時間間隔でファイルをスケジューラーに追加します
private static void RestartService(string serviceName)
{
using (var controller = new ServiceController(serviceName))
{
controller.Stop();
int counter = 0;
while (controller.Status != ServiceControllerStatus.Stopped)
{
Thread.Sleep(100);
controller.Refresh();
counter++;
if (counter > 1000)
{
throw new System.TimeoutException(string.Format("Could not stop service: {0}", Constants.Series6Service.WindowsServiceName));
}
}
controller.Start();
}
}