2016-05-17 5 views
0

Ok ...そう簡単です。私は実際にはすでにほとんどの部分でこれを動作させています。しかし、プログラムが実際には停止していなくても、プログラムが不一致に見える場合があります。プログラムは単にサービスを停止し、ある場所から別の場所にファイルをコピーした後、サービスを開始します。サービスはコピーされているファイルをロックしているため、停止する必要があります。サービスが完全に停止するのを待ってから続行してください。

internal void StopTheService() 
    { 
     Logger.Log("Stopping the service."); 
     lock (myLock) { 
      var sc = new ServiceController() { ServiceName = nameOfService, MachineName = nameOfServerWithService }; 
      sc.Stop(); 
      sc.WaitForStatus(ServiceControllerStatus.Stopped); 
     } 
     Logger.Log("Service stopped."); 
    } 

internal void StartTheService() 
    { 
     Logger.Log("Starting the service."); 
     lock (myLock) { 
      var sc = new ServiceController() { ServiceName = nameOfService, MachineName = nameOfServerWithService }; 
      sc.Start(); 
      sc.WaitForStatus(ServiceControllerStatus.Running); 
     } 
     Logger.Log("Service Started."); 
    } 

このコードは、ほとんどの部分は動作しますが、問題は、それは、サービスが停止していると考えて、次のステップに移行したときに、コピーが、それが失敗したということです。次のようなwhileループで停止/開始するのを待つことができます。

while(count<5){ 
    sc.WaitForStatus(ServiceControllerStatus.Stopped); 
    count = count+1; 
} 

しかし、私はそれも失敗する可能性があると思います。私の質問は間違っているかもしれませんが、ネット上に見つからなかったものはすべて私の質問に正確に答えません。このコードを実行するアプリケーションは、マルチスレッド環境(したがってロック)です。失敗した後にアプリケーションを再実行すると、動作します。それが返すエラーは、別のファイルを開こうとすると得られる典型的な "別のプロセスで開くファイル"のエラーです。これは私がアクセスしているサービスとファイルを持つリモート環境であり、私はUACが問題ではないように管理者権限を持っていることに注意してください。

質問:どのようにしてサービスが停止または開始されてから続行するのが確実なのでしょうか?ほとんどすべてのソリューションに対応しています。質問を複製することに応答して

:これを離れて設定します

ことは、それは私がこの仕事を実行するためにアクセスしていますが、リモート・システムであるということです。重複した質問として記載されている質問は、遠隔のシナリオを特定したり表示したりするものではありません。しかし、私はそれをテストし、成功する必要があります私は答えとして投稿します。しかしそれまでは重複していません。

+0

"サービスが停止して次のステップに移動したと思うと、失敗します。" - これをデバッグしましたか?私はこれを「サービス停止ですが、OSの種類のファイルを処理するのを忘れてしまった」と見ることができます。これは実際には回避できないかもしれない厄介なバグのように聞こえます。 – TomTom

+0

@リチャード・バーカー私はこの正確な問題を抱えており、http://stackoverflow.com/a/1597244/60188はすべてうまく解決しました。 –

+0

@AntonGogolevうわー、それは古いものです。私はまったく同じ質問名​​を入力したときに、Stackoverflowはそれを見つけられませんでした。 –

答えて

0

だから、重複した質問への答えは大部分の正解でした。その答えのコード(stackoverflow.com/a/1597244/60188)は、リモートマシンの部分を除いて、ほとんど正確です。

public void StopServiceAndWaitForExit() 
    { 

     using (var controller = new ServiceController(nameOfService, nameOfServerWithService)) 
     { 
      var ssp = new SERVICE_STATUS_PROCESS(); 
      int ignored; 

      if (!QueryServiceStatusEx(controller.ServiceHandle.DangerousGetHandle(), SC_STATUS_PROCESS_INFO, ref ssp, Marshal.SizeOf(ssp), out ignored)) 
       throw new Exception("Couldn't obtain service process information."); 

      if (ssp.dwServiceType != SERVICE_WIN32_OWN_PROCESS) 
       throw new Exception("Can't wait for the service's hosting process to exit because there may be multiple services in the process (dwServiceType is not SERVICE_WIN32_OWN_PROCESS"); 

      if ((ssp.dwServiceFlags & SERVICE_RUNS_IN_SYSTEM_PROCESS) != 0) 
       throw new Exception("Can't wait for the service's hosting process to exit because the hosting process is a critical system process that will not exit (SERVICE_RUNS_IN_SYSTEM_PROCESS flag set)"); 

      if (ssp.dwProcessId == 0) 
       throw new Exception("Can't wait for the service's hosting process to exit because the process ID is not known."); 

      using (Process process = Process.GetProcessById(ssp.dwProcessId, nameOfServerWithService)) 
      { 
       var threadData = new ProcessWaitForExitData(); 

       threadData.Process = process; 

       var processWaitForExitThread = new Thread(ProcessWaitForExitThreadProc); 

       processWaitForExitThread.IsBackground = Thread.CurrentThread.IsBackground; 
       processWaitForExitThread.Start(threadData); 

       controller.Stop(); 

       lock (threadData.Sync) 
        while (!threadData.HasExited) 
         Monitor.Wait(threadData.Sync); 
      } 
     } 
    } 
0

2種類の溶液:

A.データベースやファイルへの開始/終了にそのステータスを更新するサービスコードを更新します。あなたのプログラムはステータスを読み込みます。

B.プログラムは、サービススレッドが存在するかどうかをチェックします。

+0

Aはサービスへの更新を必要とします - 私はそれを避けたいですが、 Bは可能かもしれませんが、私がリモートマシンからそれを行うことができる場合に限ります。 –

関連する問題