it-swarm.com.de

Einfachere Möglichkeit zum Debuggen eines Windows-Dienstes

Gibt es eine einfachere Möglichkeit, den Code schrittweise zu durchlaufen, als den Dienst über den Windows-Dienststeuerungs-Manager zu starten und dann den Debugger an den Thread anzuhängen? Es ist ziemlich umständlich und ich frage mich, ob es einen direkteren Ansatz gibt.

306
Mats

Wenn ich den Dienst schnell debuggen möchte, füge ich einfach eine Debugger.Break() dort ein. Wenn diese Linie erreicht ist, wird ich wieder auf VS gesetzt. Vergessen Sie nicht, diese Zeile zu entfernen, wenn Sie fertig sind.

UPDATE: Alternativ zu #if DEBUG-Pragmas können Sie auch das Conditional("DEBUG_SERVICE")-Attribut verwenden.

[Conditional("DEBUG_SERVICE")]
private static void DebugMode()
{
    Debugger.Break();
}

Rufen Sie auf Ihrer OnStart einfach diese Methode auf:

public override void OnStart()
{
     DebugMode();
     /* ... do the rest */
}

Dort wird der Code nur während des Debug-Builds aktiviert. Während Sie dabei sind, kann es hilfreich sein, eine separate Build-Konfiguration für das Service-Debugging zu erstellen.

262
jop

Ich denke auch, dass eine separate "Version" für die normale Ausführung und als Dienst der richtige Weg ist, aber ist es wirklich erforderlich, einen separaten Befehlszeilenschalter für diesen Zweck bereitzustellen?

Könntest du nicht einfach tun:

public static int Main(string[] args)
{
  if (!Environment.UserInteractive)
  {
    // Startup as service.
  }
  else
  {
    // Startup as application
  }
}

Das hätte den "Vorteil", dass Sie Ihre App einfach per Doppelklick starten können (OK, wenn Sie das wirklich brauchen) und dass Sie einfach drücken können F5 in Visual Studio (ohne dass die Projekteinstellungen geändert werden müssen, um diese /console-Option einzuschließen).

Technisch überprüft der Environment.UserInteractive, ob das Flag WSF_VISIBLE für die aktuelle Fensterstation gesetzt ist. Gibt es jedoch einen anderen Grund, aus dem er false zurückgeben würde, abgesehen davon, dass er als (nicht interaktiver) Dienst ausgeführt wird?

208
Christian.K

Als ich vor einigen Wochen ein neues Serviceprojekt aufgesetzt habe, habe ich diesen Beitrag gefunden. Obwohl es viele großartige Vorschläge gibt, habe ich immer noch nicht die gewünschte Lösung gefunden: Die Möglichkeit, die Methoden OnStart und OnStop der Serviceklassen ohne Änderung der Serviceklassen aufzurufen.

Die Lösung, die ich mir vorgestellt habe, verwendet den Environment.Interactive-Modus für die Auswahl, wie in anderen Antworten zu diesem Beitrag vorgeschlagen.

static void Main()
{
    ServiceBase[] servicesToRun;
    servicesToRun = new ServiceBase[] 
    {
        new MyService()
    };
    if (Environment.UserInteractive)
    {
        RunInteractive(servicesToRun);
    }
    else
    {
        ServiceBase.Run(servicesToRun);
    }
}

Der Helfer RunInteractive ruft mithilfe von Reflection die geschützten OnStart- und OnStop-Methoden auf:

static void RunInteractive(ServiceBase[] servicesToRun)
{
    Console.WriteLine("Services running in interactive mode.");
    Console.WriteLine();

    MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart", 
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Starting {0}...", service.ServiceName);
        onStartMethod.Invoke(service, new object[] { new string[] { } });
        Console.Write("Started");
    }

    Console.WriteLine();
    Console.WriteLine();
    Console.WriteLine(
        "Press any key to stop the services and end the process...");
    Console.ReadKey();
    Console.WriteLine();

    MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop", 
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Stopping {0}...", service.ServiceName);
        onStopMethod.Invoke(service, null);
        Console.WriteLine("Stopped");
    }

    Console.WriteLine("All services stopped.");
    // Keep the console alive for a second to allow the user to see the message.
    Thread.Sleep(1000);
}

Dies ist der gesamte Code, aber ich habe auch Komplettlösung mit Erklärungen geschrieben.

116
Anders Abel

Manchmal ist es wichtig zu analysieren, was los ist während des Starts des Dienstes. Das Anhängen an den Prozess hilft hier nicht weiter, weil Sie nicht schnell genug sind, um den Debugger während des Starts anzuhängen Der Dienst wird gestartet.

Die kurze Antwort lautet: Ich verwende die folgenden 4 Codezeilen , um dies zu tun:

#if DEBUG
    base.RequestAdditionalTime(600000); // 600*1000ms = 10 minutes timeout
    Debugger.Launch(); // launch and attach debugger
#endif

Diese werden wie folgt in die OnStart -Methode des Service eingefügt:

protected override void OnStart(string[] args)
{
    #if DEBUG
       base.RequestAdditionalTime(600000); // 10 minutes timeout for startup
       Debugger.Launch(); // launch and attach debugger
    #endif
    MyInitOnstart(); // my individual initialization code for the service
    // allow the base class to perform any work it needs to do
    base.OnStart(args);
}

Für diejenigen, die es noch nicht getan haben, habe ich detaillierte Hinweise unten aufgenommen, weil Sie leicht stecken bleiben können. Die folgenden Hinweise beziehen sich auf Windows 7x64 und Visual Studio 2010 Team Edition , sollten jedoch auch für andere Umgebungen gültig sein.


Wichtig: Stellen Sie den Dienst im "manuellen" Modus bereit (entweder mit dem Dienstprogramm InstallUtil von der VS-Eingabeaufforderung aus oder führen Sie es aus ein Service-Installationsprojekt, das Sie vorbereitet haben). Öffnen Sie Visual Studio vor Sie starten den Dienst und laden die Lösung, die den Quellcode des Dienstes enthält. Richten Sie zusätzliche Haltepunkte ein, wie Sie sie in Visual Studio benötigen. Starten Sie dann den Dienst über Service Control Panel

Aufgrund des Codes Debugger.Launch Wird ein Dialogfeld "In Servicename.exe ist eine nicht behandelte Microsoft .NET Framework-Ausnahme aufgetreten" angezeigt. erscheinen. Klicken Sie auf Elevate Ja, debuggen Servicename.exe wie im Screenshot gezeigt:
FrameworkException

Anschließend werden Sie unter Windows 7 UAC möglicherweise aufgefordert, Administratoranmeldeinformationen einzugeben. Geben Sie sie ein und fahren Sie mit fortYes:

UACPrompt

Danach erscheint das bekannte Visual Studio Just-In-Time-Debugger-Fenster . Sie werden gefragt, ob Sie mit dem ausgewählten Debugger debuggen möchten. Bevor Sie klicken Yes, wähle aus, dass du keine neue Instanz öffnen möchtest (2. Option) - eine neue Instanz wäre hier nicht hilfreich, da der Quellcode nicht hilfreich wäre wird nicht angezeigt. So wählen Sie stattdessen die zuvor geöffnete Visual Studio-Instanz aus: VSDebuggerPrompt

Nachdem Sie geklickt haben Yes, Nach einer Weile zeigt Visual Studio den gelben Pfeil rechts in der Zeile an, in der sich die Anweisung Debugger.Launch befindet, und Sie können Ihren Code debuggen (Methode MyInitOnStart, die enthält Ihre Initialisierung). VSDebuggerBreakpoint

Drücken F5 setzt die Ausführung sofort fort, bis der nächste von Ihnen vorbereitete Haltepunkt erreicht ist.

Hinweis: Um den Dienst am Laufen zu halten, wählen Sie Debug -> Alle trennen . Auf diese Weise können Sie einen Client ausführen, der mit dem Dienst kommuniziert, nachdem dieser ordnungsgemäß gestartet wurde und Sie das Debuggen des Startcodes abgeschlossen haben. Wenn Sie Shift+F5 (Beenden des Debuggens), dadurch wird der Dienst beendet. Stattdessen sollten Sie das Service Control Panel verwenden, um es zu stoppen.

Hinweis das

  • Wenn Sie ein Release, erstellen, wird der Debug-Code automatisch entfernt und der Dienst wird normal ausgeführt.

  • Ich verwende Debugger.Launch(), welches startet und einen Debugger anfügt . Ich habe auch Debugger.Break() getestet, was hat nicht funktioniert , da beim Start kein Debugger angehängt ist des Dienstes noch (verursacht die "Fehler 1067: Der Prozess wurde unerwartet beendet." ).

  • RequestAdditionalTime setzt eine längere - Zeitüberschreitung für den Start des Dienstes (es ist nicht verzögert den Code selbst, fährt aber sofort mit der Anweisung Debugger.Launch fort. Andernfalls ist das Standardzeitlimit für das Starten des Dienstes zu kurz und das Starten des Dienstes schlägt fehl, wenn Sie base.Onstart(args) nicht schnell genug vom Debugger aus aufrufen. Bei einem Timeout von 10 Minuten wird die Meldung " Der Dienst hat nicht geantwortet ..." unmittelbar nach dem Start des Debuggers angezeigt.

  • Sobald Sie sich daran gewöhnt haben, ist diese Methode sehr einfach, da Sie lediglich 4 Zeilen zu einem vorhandenen Servicecode hinzufügen müssen, um schnell die Kontrolle und das Debuggen zu erlangen.

41
Matt

Was ich normalerweise tue, ist, die Logik des Dienstes in einer separaten Klasse zu kapseln und diese von einer 'Runner'-Klasse zu starten. Diese Läuferklasse kann der eigentliche Dienst oder nur eine Konsolenanwendung sein. Ihre Lösung hat also (mindestens) 3 Projekte:

/ConsoleRunner
   /....
/ServiceRunner
   /....
/ApplicationLogic
   /....
40
Paul van Brenk

In diesem YouTube-Video von Fabio Scopel wird erklärt, wie Sie einen Windows-Dienst ganz schön debuggen können ... Die eigentliche Methode dafür beginnt um 4:45 Uhr im Video ...

Hier ist der Code, der im Video erklärt wird ... in Ihrer Program.cs-Datei, fügen Sie das Zeug für den Debug-Abschnitt hinzu ... 

namespace YourNamespace
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
#if DEBUG
            Service1 myService = new Service1();
            myService.OnDebug();
            System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
#endif

        }
    }
}

Fügen Sie in Ihrer Service1.cs-Datei die OnDebug () -Methode hinzu ...

    public Service1()
    {
        InitializeComponent();
    }

    public void OnDebug()
    {
        OnStart(null);
    }

    protected override void OnStart(string[] args)
    {
        // your code to do something
    }

    protected override void OnStop()
    {
    }

Wie es funktioniert

Grundsätzlich müssen Sie eine public void OnDebug() erstellen, die die OnStart(string[] args) aufruft, da sie geschützt und von außen nicht zugänglich ist. Das void Main()-Programm wird mit #if-Präprozessor mit #DEBUG hinzugefügt. 

Visual Studio definiert DEBUG, wenn das Projekt im Debugmodus kompiliert wird. Dadurch kann der Debug-Abschnitt (unten) ausgeführt werden, wenn die Bedingung erfüllt ist

Service1 myService = new Service1();
myService.OnDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);

Und es läuft wie eine Konsolenanwendung. Sobald alles OK ist, können Sie den Modus Release ändern und der reguläre else-Abschnitt löst die Logik aus

23
Jason Miller

UPDATE

Dieser Ansatz ist bei weitem der einfachste:

http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx

Ich lasse meine ursprüngliche Antwort unten für die Nachwelt.


In meinen Diensten gibt es normalerweise eine Klasse, die einen Timer enthält, da der Dienst in regelmäßigen Abständen prüfen soll, ob Arbeit vorliegt.

Wir bauen die Klasse neu auf und rufen während des Dienststarts StartEventLoop () auf. (Diese Klasse kann auch problemlos von einer Konsolen-App verwendet werden.)

Der schöne Nebeneffekt dieses Entwurfs ist, dass die Argumente, mit denen Sie den Timer einrichten, verwendet werden können, um eine Verzögerung zu verursachen, bevor der Dienst tatsächlich funktioniert, sodass Sie Zeit haben, einen Debugger manuell anzuschließen.

p.s. Wie man den Debugger manuell anfügt an einen laufenden Prozess ...?

using System;
using System.Threading;
using System.Configuration;    

public class ServiceEventHandler
{
    Timer _timer;
    public ServiceEventHandler()
    {
        // get configuration etc.
        _timer = new Timer(
            new TimerCallback(EventTimerCallback)
            , null
            , Timeout.Infinite
            , Timeout.Infinite);
    }

    private void EventTimerCallback(object state)
    {
        // do something
    }

    public void StartEventLoop()
    {
        // wait a minute, then run every 30 minutes
        _timer.Change(TimeSpan.Parse("00:01:00"), TimeSpan.Parse("00:30:00");
    }
}

Außerdem habe ich Folgendes getan (bereits in den vorherigen Antworten erwähnt, jedoch mit den [#if] -Flags des bedingten Compilers, um zu verhindern, dass es in einem Release-Build ausgelöst wird).

Ich habe auf diese Weise aufgehört, weil wir manchmal vergessen, Release zu bauen und eine Debugger-Unterbrechung in einer auf einem Client-Demo ausgeführten App zu haben (peinlich!).

#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
    System.Diagnostics.Debugger.Break();
}
#endif
14
rohancragg

static void Main()
{
#if DEBUG
                // Run as interactive exe in debug mode to allow easy
                // debugging.

                var service = new MyService();
                service.OnStart(null);

                // Sleep the main thread indefinitely while the service code
                // runs in .OnStart

                Thread.Sleep(Timeout.Infinite);
#else
                // Run normally as service in release mode.

                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]{ new MyService() };
                ServiceBase.Run(ServicesToRun);
#endif
}
13
Thomas Bratt

Sie können den Dienst auch über den Befehl Prompt (sc.exe) starten.

Ich persönlich würde den Code in der Debugging-Phase als eigenständiges Programm ausführen. Wenn die meisten Fehler behoben sind, können Sie als Dienst ausgeführt werden.

10
akauppi

Früher hatte ich einen Befehlszeilenschalter, mit dem das Programm entweder als Dienst oder als normale Anwendung gestartet werden konnte. Dann würde ich in meiner IDE den Schalter so einstellen, dass ich meinen Code schrittweise durchgehen kann.

Bei einigen Sprachen können Sie tatsächlich feststellen, ob sie in einer IDE ausgeführt wird, und diese Option automatisch ausführen.

Welche Sprache verwendest du?

10
RB.

Ich denke, es hängt davon ab, welches Betriebssystem Sie verwenden. Aufgrund der Trennung zwischen den Sitzungen ist es viel schwieriger, Vista mit Services zu verbinden.

Die zwei Optionen, die ich in der Vergangenheit verwendet habe, sind:

  • Verwenden Sie GFlags (in den Debugging-Tools für Windows), um einen permanenten Debugger für einen Prozess einzurichten. Dies ist in dem Registrierungsschlüssel "Image File Execution Options" enthalten und ist unglaublich nützlich. Ich denke, Sie müssen die Service-Einstellungen anpassen, um "Interact with Desktop" zu aktivieren. Ich verwende dies für alle Arten von Debugging, nicht nur für Services.
  • Die andere Option besteht darin, den Code ein wenig zu trennen, so dass der Serviceteil mit einem normalen App-Start austauschbar ist. Auf diese Weise können Sie ein einfaches Befehlszeilenflag verwenden und als Prozess (und nicht als Dienst) starten, wodurch das Debuggen erheblich vereinfacht wird.

Hoffe das hilft.

8
RichS

Verwenden Sie die Bibliothek TopShelf .

Erstellen Sie eine Konsolenanwendung und konfigurieren Sie das Setup in Ihrem Main

class Program
    {
        static void Main(string[] args)
        {
            HostFactory.Run(x =>
            {

                // setup service start and stop.
                x.Service<Controller>(s =>
                {
                    s.ConstructUsing(name => new Controller());
                    s.WhenStarted(controller => controller.Start());
                    s.WhenStopped(controller => controller.Stop());
                });

                // setup recovery here
                x.EnableServiceRecovery(rc =>
                {
                    rc.RestartService(delayInMinutes: 0);
                    rc.SetResetPeriod(days: 0);
                });

                x.RunAsLocalSystem();
            });
        }
}

public class Controller
    {
        public void Start()
        {

        }

        public void Stop()
        {

        }
    }

Um Ihren Dienst zu debuggen, drücken Sie einfach F5 in Visual Studio.

Geben Sie zur Installation des Dienstes cmd "console.exe install" ein.

Sie können den Dienst dann im Windows-Dienstmanager starten und stoppen.

7
Misterhex

Wenn ich einen Dienst schreibe, stelle ich die gesamte Dienstlogik in ein DLL-Projekt ein und erstelle zwei "Hosts", die in diese DLL aufgerufen werden. Einer ist ein Windows-Dienst und der andere eine Befehlszeilenanwendung.

Ich benutze die Befehlszeilenanwendung zum Debuggen und füge den Debugger nur bei Fehlern an den realen Dienst an, die ich in der Befehlszeilenanwendung nicht reproduzieren kann.

Wenn Sie diesen Ansatz verwenden, müssen Sie nur daran denken, dass Sie den gesamten Code testen müssen, während Sie in einem echten Dienst ausgeführt werden. Das Befehlszeilentool ist jedoch eine Nice-Debugging-Hilfe. Es ist eine andere Umgebung und verhält sich nicht wie ein richtiger Dienst.

5
Nir

Ich möchte jeden Aspekt meines Dienstes debuggen können, einschließlich aller Initialisierungen in OnStart (), während ich ihn weiterhin mit vollem Serviceverhalten im Rahmen des SCM ausführen kann ... kein "Konsolen" - oder "App" -Modus. 

Ich mache dies, indem ich im selben Projekt einen zweiten Dienst für das Debugging erstellt habe. Wenn der Debug-Dienst wie üblich gestartet wird (d. H. Im Plugin für Dienste MMC), wird der Dienst Host-Prozess erstellt. Dadurch erhalten Sie einen Prozess, an den Sie den Debugger anschließen können, auch wenn Sie Ihren eigentlichen Dienst noch nicht gestartet haben. Nachdem Sie den Debugger an den Prozess angehängt haben, starten Sie Ihren eigentlichen Dienst, und Sie können innerhalb des Dienstlebenszyklus, einschließlich OnStart (), darauf zugreifen.

Da der Debug-Service nur einen minimalen Code-Angriff erfordert, kann er problemlos in Ihr Service-Setup-Projekt eingebunden werden. Er kann leicht aus Ihrer Produktionsversion entfernt werden, indem er eine einzelne Codezeile auskommentiert und ein einziges Projektinstallationsprogramm löscht.

Einzelheiten:

1) Wenn Sie MyService implementieren, erstellen Sie auch MyServiceDebug. Fügen Sie beide zu dem ServiceBase-Array in Program.cs hinzu:

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService(),
            new MyServiceDebug()
        };
        ServiceBase.Run(ServicesToRun);
    }

2) Fügen Sie den realen Dienst UND den Debug-Dienst zum Projektinstallationsprogramm für das Dienstprojekt hinzu:

enter image description here

Beide Services (Real und Debug) werden eingeschlossen, wenn Sie die Serviceprojektausgabe zum Setup-Projekt für den Service hinzufügen. Nach der Installation werden beide Dienste im Plugin service.msc MMC angezeigt.

3) Starten Sie den Debug-Dienst in MMC.

4) Hängen Sie in Visual Studio den Debugger an den vom Debug-Dienst gestarteten Prozess an.

5) Starten Sie den echten Dienst und genießen Sie das Debuggen.

5
BitMask777

Beim Entwickeln und Debuggen eines Windows-Dienstes führe ich ihn normalerweise als Konsolenanwendung aus, indem ich einen/console-Startparameter hinzufüge und dies überprüfe. Macht das Leben viel einfacher.

static void Main(string[] args) {
    if (Console.In != StreamReader.Null) {
        if (args.Length > 0 && args[0] == "/console") {
            // Start your service work.
        }
    }
}
4
Maurice

Wie wäre es mit Debugger.Break () in der ersten Zeile?

4
leppie

Zum Debuggen von Windows-Diensten kombiniere ich GFlags und eine von Regedit erstellte .reg-Datei.

  1. Führen Sie GFlags aus und geben Sie den exe-Namen und vsjitdebugger an
  2. Führen Sie regedit aus und gehen Sie zu dem Ort, an dem GFlags seine Optionen festlegt
  3. Wählen Sie "Export Key" aus dem Dateimenü
  4. Speichern Sie diese Datei irgendwo mit der Erweiterung .reg
  5. Wenn Sie den Dienst debuggen möchten, doppelklicken Sie auf die REG-Datei
  6. Wenn Sie das Debuggen beenden möchten, doppelklicken Sie auf die zweite .reg-Datei

Oder speichern Sie die folgenden Ausschnitte und ersetzen Sie servicename.exe durch den gewünschten Namen der ausführbaren Datei.


debugon.reg:

Windows Registry Editor Version 5.00 

 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ausführungsoptionen für Image-Dateien\servicename.exe] 
 "GlobalFlag" = "0x00000000" 
 "Debugger" = " vsjitdebugger.exe "

debugoff.reg:

Windows-Registrierungs-Editor Version 5.00 

 [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ausführungsoptionen für Image-Dateien\servicename.exe] 
 "GlobalFlag" = "0x00000000"
2
janv8000

Dies ist einiges nach der Frage, kann aber für die spätere Bezugnahme hilfreich sein. 

Wenn Sie können, würde ich vorschlagen, das ausgezeichnete Projekt TopShelf zu verwenden. Dadurch wird die Entwicklung und das Debugging eines Windows-Dienstes erheblich vereinfacht. Außerdem ist die Bereitstellung etwas einfacher. 

Check it out: http://topshelf-project.com/

1
Jeremy Wiebe
#if DEBUG
    System.Diagnostics.Debugger.Break();
#endif
1
Ervin Ter

Ich verwende eine Variation der Antwort von JOP. Mit Hilfe von Befehlszeilenparametern können Sie den Debugging-Modus in der IDE mit den Projekteigenschaften oder über den Windows-Dienstmanager einstellen.

protected override void OnStart(string[] args)
{
  if (args.Contains<string>("DEBUG_SERVICE"))
  {
    Debugger.Break();
  }
  ...
}
1
nh99

Verwenden Sie "Debugger.Break ()" für die Fehlersuche in einem vorhandenen Windows-Dienstprogramm, wie von anderen Benutzern vorgeschlagen.

Für ein neues Windows-Dienstprogramm würde ich vorschlagen, die Methode von James Michael Hare zu verwenden http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable-windows-service- template-redux.aspx

1
yyou

Für die Routine-Programmierung von Kleinigkeiten habe ich einen sehr einfachen Trick gemacht, um meinen Service leicht zu debuggen:

Beim Start des Dienstes überprüfe ich nach einem Befehlszeilenparameter "/ debug". Wenn der Dienst mit diesem Parameter aufgerufen wird, führe ich nicht den üblichen Dienststart aus, sondern starte stattdessen alle Listener und zeige nur die Meldung "Debug in progress, zum Beenden OK drücken".

Wenn mein Dienst wie üblich gestartet wird, wird er als Dienst gestartet. Wenn er mit dem Befehlszeilenparameter/debug gestartet wird, verhält er sich wie ein normales Programm.

In VS füge ich einfach/debugging als Debugging-Parameter hinzu und starte das Serviceprogramm direkt.

Auf diese Weise kann ich für die meisten kleinen Probleme problemlos debuggen. Natürlich müssen einige Dinge noch als Service debuggt werden, aber für 99% ist das gut genug.

1
Sam

Stellen Sie Ihr Debugger-Mittagessen einfach überall hin und fügen Sie Visualstudio beim Start hinzu

#if DEBUG
    Debugger.Launch();
#endif

Außerdem müssen Sie VS als Administrator starten, und Sie müssen zulassen, dass ein Prozess automatisch von einem anderen Benutzer debuggt werden kann (wie hier hier erläutert):

reg add "HKCR\AppID{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f
1
wotanii

Verwenden Sie das Windows Service Template C # -Projekt, um eine neue Dienstanwendung zu erstellen https://github.com/HarpyWar/windows-service-template

Es werden automatisch der Konsolen-/Dienstmodus erkannt, der automatische Installations-/Deinstallationsdienst Ihres Dienstes und einige der am häufigsten verwendeten Funktionen sind enthalten.

1
HarpyWar
static class Program
{
    static void Main()
    {
        #if DEBUG

        // TODO: Add code to start application here

        //    //If the mode is in debugging
        //    //create a new service instance
        Service1 myService = new Service1();

        //    //call the start method - this will start the Timer.
        myService.Start();

        //    //Set the Thread to sleep
        Thread.Sleep(300000);

        //    //Call the Stop method-this will stop the Timer.
        myService.Stop();

         #else
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service1() 
        };

        ServiceBase.Run(ServicesToRun);
         #endif
    }
}
1
Mansoor

Hier ist die einfache Methode, mit der ich den Dienst getestet habe, ohne zusätzliche "Debug" -Methoden und mit integrierten VS-Komponententests.

[TestMethod]
public void TestMyService()
{
    MyService fs = new MyService();

    var OnStart = fs.GetType().BaseType.GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

    OnStart.Invoke(fs, new object[] { null });
}

// As an extension method
public static void Start(this ServiceBase service, List<string> parameters)
{
     string[] par = parameters == null ? null : parameters.ToArray();

     var OnStart = service.GetType().GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

     OnStart.Invoke(service, new object[] { par });
}
1
MisterDr

Die beste Option ist die Verwendung des Namespaces ' System.Diagnostics '.

Fügen Sie Ihren Code wie folgt in den if if-Block für den Debug-Modus und den Freigabemodus ein, um zwischen dem Debug- und Freigabemodus in Visual Studio zu wechseln

#if DEBUG  // for debug mode
       **Debugger.Launch();**  //debugger will hit here
       foreach (var job in JobFactory.GetJobs())
            {
                //do something 
            }

#else    // for release mode
      **Debugger.Launch();**  //debugger will hit here
     // write code here to do something in Release mode.

#endif
0
Amey P Naik

Einfach einfügen

Debugger.Break();

irgendwo in Ihrem Code.

Zum Beispiel , 

internal static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        private static void Main()
        {
            Debugger.Break();
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
        }
    }

Es wird Debugger.Break(); angezeigt, wenn Sie Ihr Programm ausführen.

0

Sie haben zwei Möglichkeiten zum Debuggen.

  1. erstellen Sie eine Protokolldatei: Persönlich bevorzuge ich eine separate Protokolldatei, z. B. eine Textdatei, anstatt das Anwendungsprotokoll oder das Ereignisprotokoll zu verwenden. Dies kostet Sie jedoch viel Zeit, denn es ist immer noch schwer zu ermitteln, wo genau der Fehlerort liegt
  2. Konvertieren Sie die Anwendung in eine Konsolenanwendung: Dies ermöglicht Ihnen alle Debugging-Tools, die wir in VS verwenden können.

Bitte beziehen Sie sich auf DIESEN Blog-Beitrag, den ich für das Thema erstellt habe. 

0
Sandaru