Question

Existe-t-il un moyen plus simple de parcourir le code que de démarrer le service via le Gestionnaire de contrôle des services Windows, puis de connecter le débogueur au thread? C'est un peu lourd et je me demande s'il existe une approche plus simple.

Était-ce utile?

La solution

Si je veux déboguer rapidement le service, je viens de déposer un Debugger.Break () . Lorsque cette ligne est atteinte, cela me ramène à VS. N'oubliez pas de supprimer cette ligne lorsque vous avez terminé.

UPDATE: Au lieu des pragmas #if DEBUG , vous pouvez également utiliser l'attribut Conditional ("DEBUG_SERVICE") .

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

Sur votre OnStart , appelez simplement cette méthode:

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

Dans ce cas, le code ne sera activé que pendant les versions Debug. Pendant que vous y êtes, il peut être utile de créer une configuration de construction distincte pour le débogage du service.

Autres conseils

Je pense aussi avoir une "version" séparée pour une exécution normale et en tant que service est la voie à suivre, mais est-il vraiment nécessaire de dédier un commutateur de ligne de commande séparé à cette fin?

Ne pourriez-vous pas simplement faire:

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

Cela aurait l'avantage ", vous pouvez simplement démarrer votre application via un double clic (OK, si vous en avez vraiment besoin) et vous pouvez simplement cliquer sur F5 dans Visual Studio (sans le besoin de modifier les paramètres du projet pour inclure cette option / console ).

Techniquement, Environment.UserInteractive vérifie si l'indicateur WSF_VISIBLE est défini pour la station de fenêtre actuelle, mais existe-t-il une autre raison pour laquelle il renverrait false , en plus d'être exécuté en tant que service (non interactif)?

Lorsque j'ai mis en place un nouveau projet de service il y a quelques semaines, j'ai trouvé ce post. Bien qu'il y ait beaucoup de bonnes suggestions, je n'ai toujours pas trouvé la solution que je cherchais: la possibilité d'appeler les méthodes OnStart et OnStop des classes de service sans aucune modification du service. classes.

La solution que j'ai proposée utilise le code Environment.Interactive , tel que suggéré par d'autres réponses à ce message.

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

L'aide RunInteractive utilise la réflexion pour appeler les méthodes protégées OnStart et OnStop :

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

C’est tout le code requis, mais j’ai aussi écrit procédure pas à pas avec explications.

Parfois, il est important d'analyser ce qui se passe lors du démarrage du service. L'attachement au processus n'aide pas ici, car vous n'êtes pas assez rapide pour attacher le débogueur lorsque le service est en cours. démarrage.

La réponse courte est que j'utilise les 4 lignes de code suivantes pour ce faire:

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

Ceux-ci sont insérés dans la méthode OnStart du service comme suit:

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

Pour ceux qui ne l'ont pas encore fait, j'ai inclus des conseils détaillés ci-dessous , car vous pouvez facilement rester bloqué. Les astuces suivantes font référence à Windows 7x64 et à Visual Studio 2010 Team Edition , mais doivent également être valables pour d'autres environnements.

Important: déployez le service dans " manuel " mode (utilisez l’utilitaire InstallUtil à partir de l’invite de commande du VS ou exécutez un projet d’installateur de service que vous avez préparé). Ouvrez Visual Studio avant de démarrer le service et de charger la solution contenant le code source du service - configurez des points d'arrêt supplémentaires selon vos besoins dans Visual Studio - puis démarrez le service via le panneau de configuration du service .

En raison du code Debugger.Launch , une boîte de dialogue "Une exception Microsoft .NET Framework non gérée s'est produite dans Nom_service.exe . " apparaître. Cliquez sur  Elevate Oui, mettez au point Servicename.exe comme indiqué dans la capture d'écran:
FrameworkException

Ensuite, spécialement dans Windows 7, le contrôle de compte d'utilisateur peut vous demander de saisir les informations d'identification de l'administrateur. Entrez-les et continuez avec Oui :

UACPrompt

La fenêtre Débogueur Just-In-Time Visual Studio bien connue apparaît ensuite. Il vous demande si vous souhaitez déboguer à l'aide du débogueur sélectionné. Avant de cliquer sur Oui , sélectionnez le fait que vous ne voulez pas ouvrir une nouvelle instance (2e option) - une nouvelle instance ne serait pas utile. ici, car le code source ne serait pas affiché. Vous sélectionnez donc l'instance de Visual Studio que vous avez précédemment ouverte: VSDebuggerPrompt

Après avoir cliqué sur Oui , après un certain temps, Visual Studio affiche la flèche jaune à droite de la ligne où l'instruction Debugger.Launch est et vous pouvez déboguer votre code (méthode MyInitOnStart , qui contient votre initialisation). VSDebuggerBreakpoint

Si vous appuyez sur F5 , l'exécution se poursuit immédiatement, jusqu'à ce que le prochain point d'arrêt préparé soit atteint.

Conseil : pour que le service reste actif, sélectionnez Déboguer - > Détachez tout . Cela vous permet d’exécuter un client qui communique avec le service après le démarrage correct de celui-ci et le débogage du code de démarrage. Si vous appuyez sur Maj + F5 (arrêter le débogage), le service sera arrêté. Au lieu de cela, vous devez utiliser le Panneau de configuration du service pour l'arrêter.

Notez que

  • Si vous créez une version , le code de débogage est automatiquement supprimé et le service s'exécute normalement.

  • J'utilise Debugger.Launch () , par lequel démarre et joint un débogueur . J'ai également testé Debugger.Break () , ce qui n'a pas fonctionné , car aucun débogueur n'est encore connecté au démarrage du service. (provoquant "Erreur 1067: le processus s'est terminé de manière inattendue." ).

  • RequestAdditionalTime définit un délai plus long pour le démarrage du service ( ne retarde pas le code lui-même, mais continuera immédiatement avec l'instruction Debugger.Launch ). Sinon, le délai d'attente par défaut pour le démarrage du service est trop court et le démarrage du service échoue si vous n'appelez pas base.Onstart (args) à partir du débogueur assez rapidement. En pratique, un délai d'attente de 10 minutes permet d'éviter l'affichage du message " le service n'a pas répondu ..." immédiatement après le démarrage du débogueur.

  • Une fois que vous vous y êtes habitué, cette méthode est très simple car elle vous oblige à ajouter 4 lignes à un code de service existant, ce qui vous permet de prendre rapidement le contrôle et le débogage.

Ce que je fais habituellement, c’est d’encapsuler la logique du service dans une classe distincte et de la lancer à partir d’une classe «coureur». Cette classe de coureur peut être le service réel ou simplement une application console. Donc, votre solution a (au moins) 3 projets:

/ConsoleRunner
   /....
/ServiceRunner
   /....
/ApplicationLogic
   /....

Cette la vidéo YouTube de Fabio Scopel explique comment déboguer un service Windows de manière satisfaisante. ... la méthode actuelle commence à 04h45 dans la vidéo ...

Voici le code expliqué dans la vidéo ... dans votre fichier Program.cs, ajoutez le contenu de la section de débogage ...

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

        }
    }
}

Dans votre fichier Service1.cs, ajoutez la méthode OnDebug () ...

    public Service1()
    {
        InitializeComponent();
    }

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

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

    protected override void OnStop()
    {
    }
  

Comment ça marche

Fondamentalement, vous devez créer un public void OnDebug () qui appelle le OnStart (string [] args) car il est protégé et n'est pas accessible à l'extérieur. Le programme void Main () est ajouté avec le préprocesseur #if avec #DEBUG .

Visual Studio définit DEBUG si le projet est compilé en mode débogage. Cela permettra à la section de débogage (ci-dessous) de s'exécuter lorsque la condition est vraie

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

Et cela fonctionnera comme une application console, une fois que tout ira bien, vous pourrez changer le mode Relâcher et la section else habituelle déclenchera la logique

.

MISE À JOUR

Cette approche est de loin la plus simple:

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

Je laisse ma réponse originale ci-dessous pour la postérité.

Mes services ont tendance à avoir une classe qui encapsule un minuteur, car je veux que le service vérifie à intervalles réguliers s'il y a du travail à faire.

Nous ouvrons la classe et appelons StartEventLoop () lors du démarrage du service. (Cette classe pourrait également être facilement utilisée depuis une application de console.)

L’effet indésirable de cette conception est que les arguments avec lesquels vous configurez le minuteur peuvent être utilisés pour retarder le travail du service, afin que vous ayez le temps d'attacher un débogueur manuellement.

  

p.s. Comment attacher le débogueur manuellement à un processus en cours d'exécution? ...

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

J'avais aussi l'habitude de faire ce qui suit (déjà mentionné dans les réponses précédentes, mais avec les indicateurs conditionnels du compilateur [#if] pour éviter qu'il ne se déclenche dans une version Release).

J'ai arrêté de le faire de cette façon, car nous oublions parfois de construire Release et de faire déboguer une application exécutée sur une démonstration client (embarrassant!).

#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
    System.Diagnostics.Debugger.Break();
}
#endif
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
}

Vous pouvez également démarrer le service via l'invite de commande (sc.exe).

Personnellement, j’exécutais le code en tant que programme autonome lors de la phase de débogage et, une fois la plupart des bogues corrigés, passait à l’exécution en tant que service.

Auparavant, j’avais recours à un commutateur de ligne de commande permettant de démarrer le programme en tant que service ou en tant qu’application standard. Ensuite, dans mon IDE, je configurerais le commutateur pour pouvoir parcourir mon code.

Avec certaines langues, vous pouvez réellement détecter s’il s’exécute dans un IDE et effectuer ce changement automatiquement.

Quelle langue utilisez-vous?

Utilisez la bibliothèque TopShelf .

Créez une application console, puis configurez la configuration dans votre ordinateur principal

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()
        {

        }
    }

Pour déboguer votre service, appuyez simplement sur F5 dans Visual Studio.

Pour installer le service, entrez cmd "console.exe install"

.

Vous pouvez ensuite démarrer et arrêter le service dans Windows Service Manager.

Je pense que cela dépend du système d'exploitation que vous utilisez. Vista est beaucoup plus difficile à attacher aux services, en raison de la séparation entre les sessions.

Les deux options que j'ai utilisées par le passé sont les suivantes:

  • Utilisez GFlags (dans les outils de débogage pour Windows) pour configurer un débogueur permanent pour un processus. Cela existe dans les " Options d'exécution du fichier image " clé de registre et est incroyablement utile. Je pense que vous devrez modifier les paramètres de service pour activer "Interagir avec le bureau". J'utilise cela pour tous les types de débogage, pas seulement pour les services.
  • L’autre option consiste à séparer un peu le code afin que la partie service soit interchangeable avec un démarrage normal de l’application. De cette façon, vous pouvez utiliser un simple indicateur de ligne de commande et le lancer en tant que processus (plutôt qu'en tant que service), ce qui facilite grandement le débogage.

J'espère que cela vous aidera.

Lorsque j'écris un service, je place toute la logique de service dans un projet dll et crée deux "hôtes". cet appel dans cette dll, l’un est un service Windows et l’autre est une application en ligne de commande.

J'utilise l'application en ligne de commande pour le débogage et attache le débogueur au service réel uniquement pour les bogues que je ne peux pas reproduire dans l'application en ligne de commande.

Si vous utilisez cette approche, rappelez-vous simplement que vous devez tester tout le code lors de l'exécution d'un service réel, alors que l'outil de ligne de commande est une aide au débogage, il s'agit d'un environnement différent et il ne se comporte pas exactement comme un véritable service. .

J'aime pouvoir déboguer tous les aspects de mon service, y compris toute initialisation dans OnStart (), tout en l'exécutant avec un comportement de service complet dans le cadre du SCM ... pas de "console". ou " app " mode.

Je le fais en créant un deuxième service, dans le même projet, à utiliser pour le débogage. Le service de débogage, lorsqu'il est démarré comme d'habitude (c'est-à-dire dans le plug-in MMC des services), crée le processus hôte du service. Cela vous donne un processus pour attacher le débogueur à même si vous n'avez pas encore démarré votre vrai service. Après avoir associé le débogueur au processus, démarrez votre service réel et vous pourrez y accéder n'importe où dans le cycle de vie du service, y compris OnStart ().

Comme il nécessite une intrusion de code très minime, le service de débogage peut facilement être inclus dans votre projet de configuration de service. Il est également facilement supprimé de votre version de production en commentant une seule ligne de code et en supprimant un seul programme d'installation de projet.

Détails:

1) En supposant que vous implémentiez MyService , créez également MyServiceDebug . Ajoutez les deux au tableau ServiceBase dans Program.cs comme suit:

    /// <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) Ajoutez le service réel ET le service de débogage au programme d'installation du projet de service:

entrer la description de l'image ici

Les deux services (réel et débogage) sont inclus lorsque vous ajoutez la sortie du projet de service au projet d'installation du service. Après l’installation, les deux services apparaîtront dans le plug-in service.msc MMC.

3) Démarrez le service de débogage dans MMC.

4) Dans Visual Studio, attachez le débogueur au processus lancé par le service de débogage.

5) Démarrer le service réel et profiter du débogage.

Lors du développement et du débogage d'un service Windows, je l'exécute généralement en tant qu'application console en ajoutant un paramètre de démarrage / console et en le vérifiant. Rend la vie beaucoup plus facile.

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

Qu'en est-il de Debugger.Break () dans la première ligne?

Pour déboguer les services Windows, je combine GFlags et un fichier .reg créé par regedit.

  1. Exécuter GFlags, en spécifiant le nom du fichier exe et vsjitdebugger
  2. Exécuter regedit et aller à l'emplacement où GFlags définit ses options
  3. Choisissez " clé d'exportation " depuis le menu fichier
  4. Enregistrez ce fichier quelque part avec l'extension .reg
  5. Chaque fois que vous souhaitez déboguer le service: double-cliquez sur le fichier .reg
  6. Si vous souhaitez arrêter le débogage, double-cliquez sur le deuxième fichier .reg

Ou enregistrez les extraits suivants et remplacez nom_service.exe par le nom de l'exécutable souhaité.

debugon.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
"GlobalFlag"="0x00000000"
"Debugger"="vsjitdebugger.exe"

debugoff.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
"GlobalFlag"="0x00000000"

Pour la programmation de routine de petites choses, j'ai utilisé une astuce très simple pour déboguer facilement mon service:

Au démarrage du service, je recherche un paramètre de ligne de commande "/ debug". Si le service est appelé avec ce paramètre, je ne fais pas le démarrage habituel du service, mais démarre tous les écouteurs et affiche simplement une boîte de message "Débogage en cours, appuyez sur ok pour terminer".

Ainsi, si mon service est démarré de la manière habituelle, il démarrera en tant que service. S'il est démarré avec le paramètre de ligne de commande / debug, il se comportera comme un programme normal.

Dans VS, je vais simplement ajouter / debug en tant que paramètre de débogage et lancer le programme de service directement.

De cette façon, je peux facilement déboguer pour la plupart des problèmes mineurs. Bien sûr, certains éléments devront encore être débogués en tant que service, mais pour 99%, cela suffit.

#if DEBUG
    System.Diagnostics.Debugger.Break();
#endif

J'utilise une variante de la réponse de JOP. À l’aide des paramètres de ligne de commande, vous pouvez définir le mode de débogage dans l’EDI avec les propriétés du projet ou via le gestionnaire de services Windows.

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

Pour résoudre les problèmes liés au programme de service Windows existant, utilisez 'Debugger.Break ()' comme l'ont suggéré d'autres personnes.

Pour le nouveau programme de service Windows, je suggérerais d’utiliser la méthode de James Michael Hare http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable-windows- service-template-redux.aspx

Placez votre déjeuner du débogueur n'importe où et attachez Visualstudio au démarrage

#if DEBUG
    Debugger.Launch();
#endif

Vous devez également démarrer VS en tant qu'administrateur et permettre qu'un processus puisse être débogué automatiquement par un utilisateur différent (comme expliqué ici ):

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

Utilisez le projet Modèle de service Windows C # pour créer une nouvelle application de service https://github.com/. HarpyWar / windows-service-template

Le mode console / service est automatiquement détecté, le programme d'installation / de désinstallation automatique de votre service et plusieurs fonctionnalités les plus utilisées sont incluses.

Voici la méthode simple que j'ai utilisée pour tester le service, sans aucune "Debug" supplémentaire. méthodes et avec les tests unitaires VS intégrés.

[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 });
}
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
    }
}

Vous avez deux options pour effectuer le débogage.

  1. créer un fichier journal: Personnellement, je préfère un fichier journal séparé, tel qu'un fichier texte, plutôt que d'utiliser le journal des applications ou le journal des événements. l'emplacement est
  2. Convertissez l'application en application console: cela vous permettra d'utiliser tous les outils de débogage que nous pouvons utiliser dans les VS.

Veuillez vous reporter au CET billet de blog que j'ai créé. pour le sujet.

Il suffit de coller

Debugger.Break();

n'importe où dans votre code.

Par exemple,

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

Cela va frapper Debugger.Break (); lorsque vous exécutez votre programme.

La meilleure option consiste à utiliser l'espace de nom ' System.Diagnostics '.

Placez votre code dans if else, bloquez le mode débogage et libérez-le comme indiqué ci-dessous pour basculer entre les modes débogage et libération dans visual studio,

#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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top