Windows Dienste verwalten

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 35 Antworten in diesem Thema. Der letzte Beitrag () ist von RISSN.

    Windows Dienste verwalten

    Hallo,

    ich nutze die Möglichkeit Windows Dienste zu verwalten. Ich möchte gerne bei Inaktivität einen Dienst anhalten und bei Aktivität wieder starten. Manchmal funktioniert es auch. GetIdle ist die Zeit, die keine Aktivität am PC vorhanden ist. Ich
    lasse das ganze im Timer laufen.

    Das kommt dann auch als Ausnahme:
    Ausnahme ausgelöst: "System.InvalidOperationException" in System.ServiceProcess.dll

    Was mache ich falsch? Wenn ich alle Bedingungen raus nehme, schaltet der Dienst ab und startet auch wieder, allerdings mit der Ausnahme und ich denke, man sollte doch abfragen können,
    was der Status gerade ist.

    VB.NET-Quellcode

    1. Imports System.ServiceProcess
    2. Public Class frmMain
    3. Dim Service As New ServiceController(My.Settings.ServiceName)
    4. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    5. Try
    6. If GetIdle() = 0 And Not Service.Status = ServiceControllerStatus.Started And Not Service.Status = ServiceControllerStatus.StartPending Then
    7. Service.Start()
    8. End If
    9. If GetIdle() / 1000 > My.Settings.MaxIdleTime And Not Service.Status = ServiceControllerStatus.Stopped And Not Service.Status = ServiceControllerStatus.StopPending Then
    10. Service.Stop()
    11. End If
    12. Catch
    13. ' noch nichts eingefügt
    14. End Try
    15. lblIdleTime.Text = "Zeit inaktivität: " & GetIdle().ToString / 1000 & " Sekunden"
    16. End Class


    CodeTags korrigiert ~VaporiZed

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    RISSN schrieb:

    Ausnahme ausgelöst: "System.InvalidOperationException" in System.ServiceProcess.dll
    In welcher Zeile Deines Codes kommt diese Exception?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RISSN schrieb:

    Es wird bereits eine Instanz des Dienstes ausgeführt
    Dann musst Du halt testen, ob eine Instanz läuft.
    Frag den Status dieses Dienstes ab.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RISSN OK.
    Wollen wir zunächst aus Deinem Code ordentlichen Code machen.
    Das, was Du da in Post #1 anbietest, ist ja wohl suboptimal:
    Nach Zuweisung eines Label-Textes steht End Class.
    Instanziierung der Klasse ServiceController mit einer Settings-Instanz, die ggf. nicht initialisiert ist.
    Wie schnell tickt der Timer?
    Kann es sein, dass der zweite Tick kommt, bevor der erste abgearbeitet ist?
    usw.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ok, ich habe nur vergessen End Sub hinzuschreiben, dass ist natürlich vorhanden. Also ansonsten würde das Programm nicht mal starten. Ich habe beim Timer 100 Millisekunden. Aber sollte ein Timer nicht erst dann
    wieder starten, wenn es den Code abgearbeitet hat? Ich weiß es nicht genau, wäre für mich nur logisch. Ich habe diese Funktion mit dem Dienst auch hier gefunden, aber leider führt sie
    nicht zum Ziel. Vielleicht ist auch der Timer das falsche Mittel. Vielleicht muss man auch immer etwas warten zwischendurch.
    @RISSN Was ist mit My.Settings.ServiceName?
    Probier mal so was:

    VB.NET-Quellcode

    1. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    2. Timer1.Stop()
    3. ' Dein Code
    4. Timer1.Start()
    5. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Bau mal zur Sicherheit ein Flag ein, welches beim Servicestartversuch gesetzt wird:

    VB.NET-Quellcode

    1. Imports System.ServiceProcess
    2. Public Class frmMain
    3. Dim Service As New ServiceController(My.Settings.ServiceName)
    4. Private ServiceWasStarted As Boolean = False
    5. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    6. If ServiceWasStarted Then Return
    7. Try
    8. If GetIdle() = 0 And Not Service.Status = ServiceControllerStatus.Started And Not Service.Status = ServiceControllerStatus.StartPending Then
    9. ServiceWasStarted = True
    10. Service.Start()
    11. End If
    12. If GetIdle() / 1000 > My.Settings.MaxIdleTime And Not Service.Status = ServiceControllerStatus.Stopped And Not Service.Status = ServiceControllerStatus.StopPending Then
    13. Service.Stop()
    14. ServiceWasStarted = False
    15. End If
    16. Catch
    17. ' noch nichts eingefügt
    18. End Try
    19. lblIdleTime.Text = "Zeit inaktivität: " & GetIdle().ToString / 1000 & " Sekunden"
    20. End Sub
    21. End Class
    Vielleicht reicht das schon.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed Nach ServiceWasStarted = True passiert in der Timer_Tick nie wieder was.
    @RISSN Und: Option Strict On :!:
    Visual Studio - Empfohlene Einstellungen

    VB.NET-Quellcode

    1. lblIdleTime.Text = "Zeit inaktivität: " & (GetIdle() / 1000).ToString & " Sekunden"
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Vielen Dank für deine Hilfe, es ändert sich bei beiden Möglichkeiten das Verhalten nicht.

    Wenn ich

    Visual Basic-Quellcode

    1. Call Shell(Environ$("COMSPEC") & " /c net start " & My.Settings.ServiceName, vbHide)


    benutze, dann funktioniert es. Ich habe nur gedacht, wenn es den ServiceController gibt, sollte man den auch nutzen und man hätte gleich den Status.
    @RodFromGermany: :S Stimmt, da sollte wohl das eher so gestaltet werden:

    VB.NET-Quellcode

    1. If GetIdle() = 0 And Not Service.Status = ServiceControllerStatus.Started And Not Service.Status = ServiceControllerStatus.StartPending Then
    2. ServiceWasStarted = True
    3. Service.Start()
    4. ServiceWasStarted = False
    5. End If
    6. If GetIdle() / 1000 > My.Settings.MaxIdleTime And Not Service.Status = ServiceControllerStatus.Stopped And Not Service.Status = ServiceControllerStatus.StopPending Then
    7. Service.Stop()
    8. End If
    Und dann sollte die Variable auch besser in ServiceGetsStarted umbenannt werden.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ok, prüf mal durch Setzen von Haltepunkten, wie oft Service.Start() aufgerufen wird. Kommt der Absturz schon nach dem ersten Aufruf oder wird Service.Start() mehrfach aufgerufen?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Wie lange braucht der Dienst, um von Nothing (Urstart) auf Started umzuschalten?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    VaporiZed schrieb:

    Ok, prüf mal durch Setzen von Haltepunkten, wie oft Service.Start() aufgerufen wird. Kommt der Absturz schon nach dem ersten Aufruf oder wird Service.Start() mehrfach aufgerufen?


    dafür habe ich ja abgefragt ob der Dienst läuft, aber genau dort sehe ich das Problem.

    VB.NET-Quellcode

    1. Try
    2. If GetIdle() = 0 And Service.Status = ServiceControllerStatus.Stopped Then
    3. Service.Start()
    4. lblInfo.Text = "Dienst " & Service.DisplayName & " läuft"
    5. ElseIf GetIdle() / 1000 > My.Settings.MaxIdleTime And Service.Status = ServiceControllerStatus.Running Then
    6. Service.Stop()
    7. lblInfo.Text = "Dienst " & Service.DisplayName & " läuft nicht"
    8. End If
    9. Catch
    10. End Try


    CodeTags korrigiert ~VaporiZed

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Wann liefert

    RISSN schrieb:

    VB.NET-Quellcode

    1. GetIdle()
    0 zurück?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RISSN schrieb:

    GetIdle() / 1000
    Pack die Sekunden-Umrechnung nach da innen und hantiere außen mit Sekunden statt Millisekunden.
    Vielleicht solltest Du testen, ob die Service-Instanz valid ist.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RISSN schrieb:

    dafür habe ich ja abgefragt ob der Dienst läuft, aber genau dort sehe ich das Problem.
    Prüfen. Nicht vermuten. Das heißt: Auch wenn Du glaubst, dass das Programm macht, was Du denkst, überprüf es trotzdem, wenn es nicht so läuft, wie Du dachtest. Daher: Exception beim 1. Service.Start oder beim 2.? Beim 1.: Etwas Grundsätzliches stimmt nicht. Entweder läuft der Service versehentlich schon oder der Aufruf an sich ist falsch. Zu prüfen, indem Du den Service nicht durch einen Timer, sondern manuell durch einen ButtonKlick startest. Wenn die Exception beim 2x Aufruf von Service.Start kommst, musst Du prüfen, wie es soweit kommen konnte, denn genau der Doppelstart soll ja eben nicht geschehen.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.