Announcement

Collapse
No announcement yet.

Status des Neustarts per Remote abfragen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Status des Neustarts per Remote abfragen

    Moin,

    Ich habe mal eine technische Frage, so ganz ohne Code o.ä.

    Ich habe eine kleine Oberfläche, über die wir jeden Server aus unserem RZ neu starten können im Bedarfsfall.
    Nun möchte ich anzeigen, in welchem Status sich der Neustart befindet. Auf welches Kriterium kann ich zurückgreifen?
    Dienste scheiden aus meiner Sicht aus, da es ja einige Sekunden dauern kann, bis der beendet wird für den Neustart.

    Mein Ziel ist also:
    Ich klicke auf Server A => Server A bekommt Restart Anweisung
    UI soll während des Restarts orange angezeigt werden
    Sobald Server wieder da => Standardfarben UI

    Wie ich das visuell mache, ist alles klar, ich weiß halt nur nicht, woran ich zuverlässig erkenne, ob der Server neu gestartet wurde oder noch gar nicht angefangen hat damit.

    Ich hoffe, man versteht mein wirres Zeugs


    Danke für Tipps
    PHP rocks!
    Eine Initiative der PHP Community

  • #2
    Ich habe dazu mal ein wenig rum experimentiert und bin zu einem aus meiner Sicht zumindest brauchbaren Ergebnis gekommen.

    Die grundsätzliche Logik sieht auf das wesentliche gekürzt so aus:
    Code:
        await Task.Run(() =>
        {
            if (Server_ShutdownRestart(server_name))
                is_restarted = Server_ObserveActivity(server_name);
        });
    
        if (!is_restarted)
        {
            MessageBox.Show($"Beim Neustart des '{server_name}' sind Probleme aufgetreten.");
            return;
        }
    Ich habe das also in zwei Methoden ausgelagert: Server_ShutdownRestart und Server_ObserveActivity.
    Die Methodennamen sind im Grunde selbsterklärend, dennoch hier kurz, was darin passiert:

    In der Methode Server_ShutdownRestart setze ich den Shutdown-Command an den Server ab:
    Code:
    try
    {
        Process p = new Process()
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\shutdown.exe"
                , Arguments = $@"/r /m \\{server} /t 0 /f"
                , UseShellExecute = false
                , CreateNoWindow = true
            }
        };
    
        p.Start();
        p.WaitForExit();
    
        return true;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Killing Service failed");
        return false;
    }
    Wenn diese Methode true zurück gibt, wird in der Server_ObserveActivity auf den Service Netlogon gewartet:
    Code:
    string service_name = "Netlogon";
    
    try
    {
        using (ServiceController sc = new ServiceController(service_name, server))
        {
            // : wait till service "Netlogon" is down
            ServiceControllerStatus[] status = new ServiceControllerStatus[] { ServiceControllerStatus.Running, ServiceControllerStatus.StopPending };
            while (status.Contains(sc.Status)) ;
    
            // : wait till service "Netlogon" is running again
            sc.WaitForStatus(ServiceControllerStatus.Running);
        }
    
        return true;
    }
    catch (Exception ex)
    {
        return false;
    }
    Der Windows-Dienst Netlogon wird von Windows immer benötigt, daher lausche ich diesen Status, um den erfolgreichen Neustart ermitteln zu können.
    Bisher scheint das gut zu funktionieren.

    Sollte jemand Bedenken oder Einwände haben, warum man das nicht so machen sollte, bitte gerne mitteilen.
    Bin für Verbesserungsvorschläge immer empfänglich.
    Zuletzt editiert von Arne Drews; 24.10.2023, 11:35. Reason: Server_ObserveActivity korrigiert
    PHP rocks!
    Eine Initiative der PHP Community

    Comment


    • #3
      KORREKTUR!

      Die Lösung war leider nur eine Scheinlösung
      Der Neustart klappt einwandfrei, aber die Überwachung funktionierte nur augenscheinlich, weil ich die Exceptions zwar abgefangen, aber bis dahin nicht darauf reagiert habe.


      Falls jemand sowas mal braucht oder andere bessere Möglichkeiten kennen, hier mal, wie es nun wirklich funktioniert:

      Die auswählbaren Server sind jeweils in einem Border eingebettet, um den Rahmen dem Status entsprechend anzupassen. Im MouseLeftButtonUp-Event rufe ich dann die Initialisierungs-Methode Server_Restart auf:
      Code:
      private async void Server_Restart(Border server)
      {
          server.BorderBrush = AppContext.ServerStatusColor_Busy;
          string server_name = server.Tag.ToString();
      
          await Task.Run(() =>
          {
              if (Server_ShutdownRestart(server_name))
              {
                  AppContext.ServerObserveCounting = 0;
                  Server_ObserveActivity(server_name, AppContext.ServerObserveServiceName, ServiceControllerStatus.Stopped);
              }
          });
      
          server.BorderBrush = AppContext.ServerStatusColor_Running;
          AppContext.DebugOverTeamsWebhook_ServerRestart(server_name);
      }
      Die Methode Server_ShutdownRestart ist wenig spektaktulär und kaum verändert:
      Code:
      private bool Server_ShutdownRestart(string server)
      {
          try
          {
              Process p = new Process()
              {
                  StartInfo = new ProcessStartInfo
                  {
                      FileName = Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\shutdown.exe"
                      , Arguments = $@"/r /m \\{server} /t 0 /f"
                      , UseShellExecute = false
                      , CreateNoWindow = true
                  }
              };
      
              p.Start();
              p.WaitForExit();
      
              return true;
          }
          catch (Exception ex)
          {
              MessageBox.Show(ex.Message, "Killing Service failed");
              return false;
          }
      }
      Die Server_ObserveActivity hingegen hat sich komplett geändert:
      Code:
      private bool Server_ObserveActivity(string server, string service, ServiceControllerStatus status)
      {
          if (AppContext.ServerObserveCounting++ > AppContext.ServerObserveCountingMax)
              return (AppContext.ServerObserveFailedByTimeOut = true);
      
          try
          {
              using (ServiceController sc = new ServiceController(service, server))
                  sc.WaitForStatus(status);
      
              return true;
          }
          catch (InvalidOperationException)
          {
              Thread.Sleep(AppContext.ServerObserveCountingDelay);
              return Server_ObserveActivity(server, service, ServiceControllerStatus.Running);
          }
      }
      Bei ersten Aufruf ( ausgehend von der Server_Restart ) wird auf den Status Stopped gewartet.
      Wenn der Server heruntergefahren ist, wird an der Stelle eine InvalidOperationException geworfen, die ich abfange. An der Stelle setze ich den Task für 2 bis 3 Sekunden in einen Schlaf und rufe dann die gleiche Methode wieder auf, mit dem Unterschied, dass ich auf den Status Running warte. Solange der Server-Dienst nicht erreichbar ist, wird sich das Szenario wiederholen, allerdings begrenzt durch eine maximale Anzahl an Versuchen.

      Wenn der Dienst wieder erreichbar ist, wird die UI aktualisiert und alles ist schick.
      Getestet und funktioniert bis jetzt einwandfrei.

      Trotzdem die Frage:
      Ist das ein brauchbarer Lösungsweg? Ich finde im Netz tatsächlich nichts, zu dem Thema, wie ich einen Remote Computer beim Neustart überwache.
      Bin für Vorschläge, Tipps & Co. offen.

      Gruß Arne
      PHP rocks!
      Eine Initiative der PHP Community

      Comment

      Working...
      X