Windowsサービスをプログラムで自動的に再起動するにはどうすればよいですか?
-
03-07-2019 - |
質問
.NETで堅牢なコードを記述して、Windowsサービス(サーバー2003)がそれ自体を再起動できるようにする必要があります。そうするための最良の方法は何ですか?それを行うための.NET APIはありますか?
解決
失敗後にサービスを再起動するように設定します(コントロールパネルでサービスをダブルクリックし、それらのタブを見てください-名前を忘れました)。その後、サービスを再起動する場合はいつでも、 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()
サービスを実行しているユーザーアカウントに、サービスを停止および再起動する権限があることを確認することはできません。
自分を再起動するDOSコマンドプロンプトであるプロセスを作成できます。
Process process = new Process();
process.StartInfo.FileName = "cmd";
process.StartInfo.Arguments = "/c net stop \"servicename\" & net start \"servicename\"";
process.Start();
const string strCmdText = "/C net stop \"SERVICENAME\"&net start \"SERVICENAME\"";
Process.Start("CMD.exe", strCmdText);
SERVICENAME
はサービスの名前です(サービス名のスペースを説明するために二重引用符が含まれます。それ以外の場合は省略できます)。
クリーン、自動再起動の構成は不要です。
それを再起動する理由によって異なります。
サービスを定期的に自動削除する方法を探している場合は、サービスでタイマーを実行して、定期的にパージルーチンを発生させることができます。
障害時に再起動する方法を探している場合-サービスホスト自体は、セットアップ時にその機能を提供できます。
では、なぜサーバーを再起動する必要があるのですか?何を達成しようとしていますか?
自己完結型のサービスではできないと思います(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) { }
}
Windowsスケジューラを使用して、サービスの再起動をスケジュールします。問題は、自分で再起動できないが、自分で停止できることです。 (本質的には、あなたが座っているブランチを切り離しました...私のアナロジーが得られれば)あなたはあなたのために別のプロセスを必要とします。 Windowsスケジューラは適切なものです。ワンタイムタスクをスケジュールして、サービスを再起動して(サービス自体からでも)すぐに実行します。
それ以外の場合は、「シェパーディング」を作成する必要があります。あなたのためにそれを行うプロセス。
それができるとは思わない。サービスが「停止」されると、完全にアンロードされます。
さて、OK、私が思うに常に方法があります。たとえば、デタッチプロセスを作成してサービスを停止し、再起動して終了することができます。
質問に対する最初の回答は最も簡単な解決策です:" Environment.Exit(1)"これをWindows Server 2008 R2で使用していますが、完全に機能します。サービスは自動的に停止し、O / Sは1分間待機してから再起動します。
別のappdomainを作成して、アプリケーションコードをホストします。再起動が必要な場合、プロセス(windowsサービス)の代わりにappdomainをアンロードおよび再ロードできます。これがIISアプリプールの仕組みです。asp.netアプリを直接実行せず、個別のappdmainを使用します。
より良いアプローチは、アプリケーションのラッパーとしてNTサービスを利用することです。 NTサービスが開始されると、アプリケーションは「アイドル」状態で開始できます。コマンドの開始を待機しているモード(または自動的に開始するように構成されているモード)。
自動車を考えてみてください。車が始動すると、アイドル状態で始まり、コマンドが前進または後退するのを待ちます。これにより、アプリケーションの公開方法を選択できるため、リモート管理が向上するなど、他の利点も得られます。
パスするだけで、さらに情報を追加すると思いました...
例外をスローすることもできます。これにより、Windowsサービスが自動的に閉じられ、自動再起動オプションが有効になります。これに関する唯一の問題は、PCに開発環境がある場合、JITが起動すると、デバッグY / Nを示すプロンプトが表示されます。いいえと言うと、閉じてから、適切に再起動します。 (JITのないPCでは、すべて正常に機能します) 理由は、このJITはWin 7で新しく(XPなどで正常に動作するため)、JITを無効にする方法を見つけようとしているためです。...ここで述べたEnvironment.Exitメソッドを試すことができますそれも機能します。
クリスチャン:ブリストル、イギリス
次のようなrestart.batファイルを作成します
@echo on
set once="C:\Program Files\MyService\once.bat"
set taskname=Restart_MyService
set service=MyService
echo rem %time% >%once%
echo net stop %service% >>%once%
echo net start %service% >>%once%
echo del %once% >>%once%
schtasks /create /ru "System" /tn %taskname% /tr '%once%' /sc onstart /F /V1 /Z
schtasks /run /tn %taskname%
その後、%service%の開始時にタスク%taskname%を削除します
nssmは非常に優れています。これはすべてあなたのために行います
最も簡単な方法は、次のものを含むバッチファイルを作成することです
ネットストップ ネットスタート
必要な時間間隔でファイルをスケジューラに追加します
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();
}
}