回答:
失敗後にサービスを再起動するように設定します(コントロールパネルでサービスをダブルクリックし、タブを見回してください-名前を忘れました)。次に、サービスを再起動したいときはいつでもEnvironment.Exit(1)
(またはゼロ以外の戻り値を)呼び出すだけで、OSがサービスを再起動します。
Service.ExitCode = 1
からService.Stop()
、サービスリカバリ設定画面の[エラーのあるストップのアクションを有効にする]チェックボックスをオンにして実行できます。この方法でこれを行うと、適切なシャットダウンが可能になり、再起動がトリガーされます。
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
あなたのサービスの名前です(サービス名にスペースが、そうでない場合は省略することができるため、二重引用符は、アカウントに含まれています)。
クリーンで、自動再起動構成は必要ありません。
再起動する理由によって異なります。
サービス自体を定期的にクリーンアップする方法を探しているだけなら、定期的にパージルーチンを引き起こすタイマーをサービスで実行することができます。
障害時に再起動する方法を探している場合-サービスホスト自体は、セットアップ時にその機能を提供できます。
では、なぜサーバーを再起動する必要があるのでしょうか。何を達成しようとしていますか?
バッチファイルまたは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サービスが自動的に閉じ、自動再起動オプションが起動します。これに関する唯一の問題は、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%を削除します
アプリケーションコードをホストする別のappdomainを作成します。再起動が必要な場合は、プロセス(Windowsサービス)の代わりにappdomainをアンロードして再ロードできます。これがIISアプリプールの動作方法であり、asp.netアプリを直接実行せず、個別のappdmainを使用します。
最も簡単な方法は、次のバッチファイルを作成することです。
ネットストップネットスタート
希望する時間間隔でファイルをスケジューラに追加します
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();
}
}