2016-05-17 6 views
0

Ok so ... Einfach genug. Ich habe das eigentlich schon größtenteils geschafft. Es gibt jedoch Zeiten, in denen der Dienst nicht gestoppt wurde, obwohl das Programm nicht zu stimmen scheint. Das Programm stoppt einfach einen Dienst, kopiert Dateien von einem Ort zum anderen und startet dann einen Dienst. Der Dienst hat eine Sperre für die Dateien, die kopiert werden, sodass er gestoppt werden muss.Warten Sie, bis ein Service vollständig gestoppt wurde, bevor Sie fortfahren

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."); 
    } 

Dieser Code funktioniert in den meisten Fällen aber Problem ist, dass, wenn es der Dienst denkt gestoppt und bewegt sich auf den nächsten Schritt, die Kopie, es funktioniert nicht. Ich kann warten, bis es in einer while-Schleife Stopp/Start wie:

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

Aber ich denke, dass könnte genauso gut ausfallen. Alles, was ich nicht im Netz gefunden habe, beantwortet meine Frage nicht genau, obwohl meine Anfrage falsch ist. Die Anwendung, die diesen Code ausführt, ist eine Multithread-Umgebung (daher die Sperre). Wenn ich die Anwendung nach einem Fehler erneut ausführen, funktioniert es. Der Fehler, den es zurückgibt, ist der typische Fehler "Datei in einem anderen Prozess geöffnet", den Sie erhalten, wenn Sie versuchen, eine andere Datei zu öffnen. Bitte beachten Sie, dass dies eine Remote-Umgebung ist, die die Dienste und Dateien hat, auf die ich zugreife, und ja, ich habe Administratorrechte, so dass UAC nicht das Problem ist.

Also die Frage: Wie kann ich sicher sein, dass der Dienst gestoppt oder gestartet wurde, bevor Sie fortfahren? Ich bin offen für fast jede Lösung.

in Reaktion Frage zu duplizieren:

Die Sache, die dieses abhebt ist, dass es ein Remote-System ist, dass ich, um mich den Zugriff auf diese Arbeit zu verrichten. Die Frage, die als doppelte Frage notiert wird, spezifiziert oder zeigt kein entferntes Szenario. Ich werde es jedoch testen und sollte es gelingen, werde ich es als Antwort veröffentlichen. Bis dahin ist es jedoch kein Duplikat.

+0

"ist es, wenn es denkt, dass der Dienst gestoppt wurde und geht weiter zum nächsten Schritt, die Kopie, scheitert es." - Hast du das geklärt? Ich kann dies als "Service stoppt, aber OS Art vergessen zu bereinigen Datei behandelt" - aber sonst nichts. Das hört sich wirklich nach einem fiesen Bug an, den man einfach nicht umgehen kann (und den ich noch nie erlebt habe). – TomTom

+0

@Richard Barker Ich habe dieses genaue Problem und http://Stackoverflow.com/a/1597244/60188 alles gut gelöst. –

+0

@AntonGogolev Wow, das ist ein alter. Und Stackoverflow fand es nicht, wenn ich genau den gleichen Frage-Namen eintippte. –

Antwort

0

Ok, so war die Antwort auf doppelte Frage die richtige Antwort zum größten Teil. Der Code auf dieser Antwort (stackoverflow.com/a/1597244/60188) ist größtenteils korrekt, mit Ausnahme der entfernten Maschinenteile.

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

Zwei Lösungen:

A. Service-Code aktualisieren ihren Status auf Start/Ende Datenbank oder Datei zu aktualisieren. Ihr Programm liest den Status.

B. Ihr Programm prüft, ob die Service-Threads existieren.

+0

A erfordert ein Update auf den Dienst - ich möchte das vermeiden, aber sollte es sich ergeben, werde ich. B ist möglicherweise möglich, aber nur, wenn ich das von einer entfernten Maschine aus tun kann. –