it-swarm.com.de

Windows-Dienst muss ständig ausgeführt werden

Ich habe einen Windows-Dienst mit dem Namen ProxyMonitor erstellt. Im Moment bin ich dabei, den Dienst zu installieren und deinstallieren, so wie ich es will.

Also führe ich die Anwendung so aus:

C:\\Windows\\Vendor\\ProxyMonitor.exe /install

Ziemlich selbsterklärend, und dann habe ich services.msc und und den Dienst gestartet, aber wenn ich das tue, erhalte ich die folgende Meldung:

Der Proxy-Überwachungsdienst auf dem lokalen Computer wurde gestartet und dann beendet. Einige Dienste werden automatisch angehalten, wenn keine Arbeit zu erledigen ist, z. B. Leistungsprotokolle und Warnungsdienste

Mein Code sieht so aus:

public static Main(string[] Args)
{
    if (System.Environment.UserInteractive)
    {
        /*
            * Here I have my install logic
        */
    }
    else
    {
        ServiceBase.Run(new ProxyMonitor());
    }
}

Und dann in der ProxyMonitor-Klasse habe ich:

public ProxyMonitor()
{
}

protected override void OnStart(string[] args)
{
    base.OnStart(args);
    ProxyEventLog.WriteEntry("ProxyMonitor Started");

    running = true;
    while (running)
    {
        //Execution Loop
    }
}

und onStop() Ich ändere einfach die Variable running in false;

Was muss ich tun, um den Dienst ständig aktiv zu machen, da ich das Netzwerk überwachen muss, muss ich Änderungen nachverfolgen usw.


Update: 1

protected override void OnStart(string[] args)
{
     base.OnStart(args);
     ProxyEventLog.WriteEntry("ProxyMonitor Started");

     Thread = new Thread(ThreadWorker);
     Thread.Start();
 }

Innerhalb der ThreadWorker habe ich ProxyEventLogger.WriteEntry("Main thread entered"), das nicht ausgelöst wird.

50
RobertPitt

Der OnStart()-Rückruf muss rechtzeitig zurückgegeben werden. Sie sollten also einen Thread starten, in dem alle Ihre Arbeiten ausgeführt werden. Ich würde empfehlen, folgende Felder zu Ihrer Klasse hinzuzufügen:

using System.Threading;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;

Das _thread-Feld enthält einen Verweis auf das System.Threading.Thread-Objekt, das Sie im OnStart()-Callback erstellen. Das Feld _shutdownEvent enthält ein Ereigniskonstrukt auf Systemebene, das verwendet wird, um zu signalisieren, dass der Thread beim Herunterfahren des Dienstes nicht mehr ausgeführt wird.

Erstellen und erstellen Sie Ihren Thread im OnStart()-Callback.

protected override void OnStart(string[] args)
{
     _thread = new Thread(WorkerThreadFunc);
     _thread.Name = "My Worker Thread";
     _thread.IsBackground = true;
     _thread.Start();
}

Sie benötigen eine Funktion mit dem Namen WorkerThreadFunc, damit dies funktioniert. Sie muss mit der System.Threading.ThreadStart Delegat-Signatur übereinstimmen.

private void WorkerThreadFunc()
{
}

Wenn Sie nichts in diese Funktion einfügen, wird der Thread gestartet und sofort heruntergefahren. Sie müssen also eine Logik einfügen, die den Thread während der Arbeit lebendig hält. Hier ist der _shutdownEvent praktisch.

private void WorkerThreadFunc()
{
    while (!_shutdownEvent.WaitOne(0)) {
        // Replace the Sleep() call with the work you need to do
        Thread.Sleep(1000);
    }
}

Die while-Schleife prüft, ob die Variable ManualResetEvent "gesetzt" ist oder nicht. Da wir das Objekt mit false oben initialisiert haben, gibt diese Prüfung den Wert false zurück. In der Schleife schlafen wir für 1 Sekunde. Sie sollten dies durch die Arbeit ersetzen, die Sie ausführen müssen - Proxy-Einstellungen überwachen usw.

Schließlich möchten Sie im OnStop()-Rückruf Ihres Windows-Dienstes signalisieren, dass der Thread nicht mehr ausgeführt wird. Dies ist einfach mit dem _shutdownEvent.

protected override void OnStop()
{
     _shutdownEvent.Set();
     if (!_thread.Join(3000)) { // give the thread 3 seconds to stop
         _thread.Abort();
     }
} 

Hoffe das hilft.

135
Matt Davis

Sie müssen Ihren OnStart-Handler beenden, damit der Service-Controller erkennt, dass Ihr Service tatsächlich gestartet wurde. Damit es so funktioniert, wie Sie es möchten, können Sie einen Timer starten, der in einem Intervall tickt und verarbeitet, wenn er tickt.

Bearbeiten:

Versuchen Sie, ein System.Diagnostics.Debugger.Launch () in Ihre OnStart zu setzen, um zu sehen, was passiert (und einen Haltepunkt in ThreadWorker). Ich würde empfehlen, dies in #if DEBUG einzuhüllen, um sicherzustellen, dass es nicht bereitgestellt wird.

Mir wurde gerade auch klar, dass Sie Ihrer Thread keinen Namen geben:

 Thread myThread = new Thread(ThreadWorker);
 myThread.Start();
6
Mark Avenius

Das Hinzufügen einer while-Schleife in der OnStart-Methode ist sicherlich nicht möglich. Dies sagt dem Betriebssystem, dass der Dienst nicht gestartet wurde, weil er die Methode OnStart nicht sicher verlassen konnte. Normalerweise erstelle ich eine Timer, die in der OnStart-Methode aktiviert ist. Dann rufe ich in der Ticks-Methode die notwendige Methode auf, damit der Antrag ausgeführt werden kann.

Alternativ können Sie Folgendes tun:

// The main entry point for the process 
static void Main() 
{ 
    System.ServiceProcess.ServiceBase[] ServicesToRun; 
    ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinService1() }; 
    System.ServiceProcess.ServiceBase.Run(ServicesToRun); 
} 

Weitere Informationen zu den Windows-Diensten erhalten Sie ein Skelettbeispiel hier .

2
Neil Knight

Beispielcode, der mithilfe einer Konsolenanwendung demonstriert wird. hoffe das wird helfen ..  

 class Program
{
    private static CancellationTokenSource _cancellationTokenSource;
    private static ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
    private static Thread _serviceStartThread;
    private static Thread _serviceStopThread;

    private static int workcounter = 0;
    static void Main(string[] args)
    {

        _cancellationTokenSource = new CancellationTokenSource();
        _serviceStartThread = new Thread(DoWork);
        _serviceStopThread = new Thread(ScheduledStop);
        StartService();
        StopService();
    }

    private static void StartService()
    {
        _serviceStartThread.Start();

    }

    private static void StopService()
    {
        _serviceStopThread.Start();
    }


    /// <summary>
    /// Triggers a cancellation event for stopping the service in a timely fashion.
    /// </summary>
    private static void ScheduledStop()
    {
        while (!_shutdownEvent.WaitOne(0))
        {
            if (workcounter == 10)
            {
                _cancellationTokenSource.Cancel();
            }
        }
    }

    /// <summary>
    /// Represents a long running Task with cancellation option
    /// </summary>
    private static void DoWork()
    {

        while (!_shutdownEvent.WaitOne(0))
        {
            if(!_cancellationTokenSource.Token.IsCancellationRequested)
            {
                workcounter += 1;
                Console.Write(Environment.NewLine);
                Console.Write("Running...counter: " + workcounter.ToString());
                Thread.Sleep(1000);//Not needed, just for demo..
            }
            else
            {
                Console.Write(Environment.NewLine);
                Console.Write("Recieved cancellation token,shutting down in 5 seconds.. counter: " + workcounter.ToString());
                _shutdownEvent.Set();
                Thread.Sleep(5000);//Not needed, just for demo..
            }

        }
    }
}
2

Warum erstellen Sie in Ihrer Lösung vom Typ Windows-Dienst kein neues Projekt? Dadurch werden alle Strukturen eingerichtet, die Sie implementieren müssen, einschließlich der Handler für Service-Start/Stopp-Ereignisse.

0
Gabriel Magana