调试Windows服务的简便方法


Answers:


271

如果我想快速调试该服务,只需Debugger.Break()在其中插入一个即可。当到达那条线时,它将使我回到VS。完成后,请不要忘记删除该行。

更新:作为#if DEBUG编译指示的替代方法,您也可以使用Conditional("DEBUG_SERVICE")属性。

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

在您的OnStart,只需调用此方法:

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

在那里,将仅在Debug构建期间启用代码。当您在使用它时,为服务调试创建一个单独的构建配置可能会很有用。


45
或者,您可以使用Debugger.Launch(),而必须在Systems.Diagnostics命名空间中包含using语句。
Omar Kooheji

1
您的博客文章运行得很好,并节省了我的时间:)但是Debugger.Break()不适用于我。似乎由于某些与优化有关的原因,.Net跳过了DebugMode函数。
Bizhan 2011年

3
当Debugger.Break()不起作用时,Debugger.Launch()对我有用。(流程退出,代码255。)
Oliver Bock 2014年

你们如何使它工作?什么都没发生。我试过Break()和Launch()。
4thSpace 2016年

13
@ 4thSpace:1.为您的服务创建一个安装程序,以便您可以安装服务。2.添加行Debugger.Launch();。在Main()的开头。3.在调试模式下构建代码。4.用debug-dll覆盖已安装的dll。5.从Windows服务面板启动服务。现在出现一个弹出窗口,要求您附加到调试器。这种方式对我有用。希望对您也是如此。
ffonz '16

210

我还认为,为正常执行和作为服务使用单独的“版本”是可行的方法,但是是否真的需要为此目的专门使用单独的命令行开关?

你不能只是做:

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

那将具有“好处”,您可以通过双击来启动您的应用程序(如果确实需要,可以单击确定),并且只需F5在Visual Studio中单击即可(无需修改项目设置以包括该/consoleOption)。

从技术上讲,Environment.UserInteractive检查是否WSF_VISIBLE为当前窗口站设置了Flag,但是false除了作为(非交互式)服务运行之外,还有其他原因会返回它吗?


大!我之前使用“ if #debug”方法作为应用程序(如果进行调试)启动,否则就作为服务启动。如果您要调试该应用程序,则导致该应用程序不能作为服务运行,但是您的解决方案解决了此问题,并使其在服务/应用程序和发行版/调试的所有四个组合中都可以运行。
乔纳斯(Jonas)2010年

29
如果您不希望该程序在双击时运行(用户可能会感到困惑并运行多个实例,等等),则可以使用System.Diagnostics.Debugger.IsAttached代替Environment.UserInteractive
Blorgbeard将于

5
但是除了作为(非交互式)服务运行之外,还有其他原因导致它返回false吗? 我可以想到一个:不附在控制台上的计划任务。
霍根

7
我在这种情况下使用命令行参数。--install安装服务,--uninstall卸载服务,--interactive将应用程序作为应用程序运行。我在项目选项(调试>命令参数)中添加了--interactive。这样我就可以轻松地从VS进行调试。双击不会创建不必要的运行实例,因为需要--interactive。只是我的2美分。
EmirAkaydın2012年

@EmirAkaydın是的,实际上我也具有命令行参数“ backup”。但是,我实际上希望在双击时有一个“交互式”实例,并且没有,并且出现有关不能以这种方式启动服务的错误消息。我猜目标不定;-)
Christian.K

123

几周前,当我建立一个新的服务项目时,我发现了这篇文章。尽管有很多不错的建议,但我仍然没有找到我想要的解决方案:无需修改服务类即可调用服务类OnStartOnStop方法的可能性。

我想出的解决方案使用Environment.Interactive选择运行模式,如本文其他答案所建议。

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

RunInteractive助手使用反射来调用保护OnStartOnStop方法:

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

这是所需的全部代码,但我还编写了演练并附有解释。


这是ServiceBase []的良好扩展方法。我的解决方案中有多个服务,因此我没有为Program.cs提供通用的基类,而只是调用servicesToRun.RunInteractive(args)。不错的解决方案@Anders!
David Keaveny

3
确实是很好的解决方案。我按照David的建议为ServiceBase []创建了一个简单的扩展,该扩展允许只用一行代码运行服务:pastebin.com/F0fhhG2R
Funbit

4
+1我的一位前同事创建了一个“ EasyRunService”基类(该基类继承了ServiceProcess),该基类做了几乎相同的事情,但不需要进行反思(因为OnStart现在在基类中)。这确实使调试Windows服务变得轻而易举。
sondergard 2015年

3
@ Chazt3n确保您的项目输出类型设置为“控制台应用程序”。对于服务安装,选择哪种输出类型都没有关系,其行为相同。
Funbit

2
仍然是一个很好的解决方案!我唯一要添加的内容(如所示walk through)是确保Console Application在尝试编译和运行之前,进入项目的属性并将输出类型更改为。在找到它Project Properties -> Application -> Output type -> Console Application。另外,为了使它对我来说正常工作,我最终不得不使用start命令运行该应用程序。例如:C:\"my app name.exe" -service对我不起作用。相反,我使用了C:\start /wait "" "my app name.exe" -service
Arvo Bowen

47

有时,重要的是分析服务启动期间发生的事情附加到进程没有帮助,因为在启动服务时您不够快地附加调试器。

简短的答案是,我正在使用以下4行代码来做到这一点:

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

将这些插入到OnStart服务的方法中,如下所示:

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

对于以前没有做过的那些人,我在下面提供了详细的提示,因为您很容易陷入困境。以下提示引用的是Windows 7x64Visual Studio 2010 Team Edition,但对其他环境也应有效。


重要:“手动”模式部署服务(使用InstallUtilVS命令提示符下的实用程序或运行您准备的服务安装程序项目)。启动服务之前,请先打开Visual Studio,然后加载包含服务源代码的解决方案-在Visual Studio中根据需要设置其他断点-然后通过“ 服务控制面板”启动该服务

由于该Debugger.Launch代码,这将导致对话框“ Servicename.exe中发生未处理的Microsoft .NET Framework异常”。出现。单击,如屏幕截图所示:Elevate Yes, debug Servicename.exe
FrameworkException

之后,尤其是在Windows 7 UAC中,可能会提示您输入管理员凭据。输入它们并继续Yes

UAC提示

此后,将出现众所周知的Visual Studio即时调试器窗口。它询问您是否要使用指定的调试器进行调试。单击之前Yes选择您不想打开新实例(第二个选项)-在这里新实例将无济于事,因为不会显示源代码。因此,您选择之前打开的Visual Studio实例: VSDebuggerPrompt

点击之后Yes经过一段时间的Visual Studio将显示在该行的黄色箭头向右,其中Debugger.Launch语句,你能调试代码(方法MyInitOnStart,其中包含你的初始化)。 VSDebuggerBreakpoint

F5立即继续执行,直到到达您准备的下一个断点。

提示:要保持服务运行,请选择Debug-> Detach all。这样,您可以在正确启动服务并完成调试启动代码后,运行与该服务进行通信的客户端。如果按Shift+F5(停止调试),将终止服务。而不是这样做,您应该使用服务控制面板将其停止。

注意的是

  • 如果构建发行版,调试代码将自动删除,并且该服务将正常运行。

  • 我正在使用Debugger.Launch(),它将启动并附加一个调试器。我也进行了测试Debugger.Break(),但没有成功,因为在服务启动时还没有连接调试器(导致“错误1067:进程意外终止。”)。

  • RequestAdditionalTime为服务启动设置更长的超时时间(它不会延迟代码本身,但会立即继续执行该Debugger.Launch语句)。否则,如果您没有base.Onstart(args)足够快地从调试器调用,则启动服务的默认超时时间将太短,并且启动服务将失败。实际上,超时10分钟可避免在调试器启动后立即看到消息“ 服务未响应...”

  • 一旦习惯了,此方法非常简单,因为它只需要在现有服务代码上添加4行,即可快速获得控制权和调试权。


1
出于好奇,您是否知道与Debugger.Launch()用户提示的用户交互是否超时?
Shiv 2014年

1
如上所述,base.RequestAdditionalTime(600000)如果base.OnStart(args)在该时间段内未调用服务控件,它将阻止该服务控件终止10分钟)。除此之外,我记得如果过一会儿不输入管理员凭据,UAC也会中止(我不知道确切的秒数,但是我认为您必须在一分钟内输入,否则UAC会中止) ,这将终止调试会话。
马特

2
我发现这是调试CustomCommand消息的最佳方法。+1。
贾斯汀

40

我通常要做的是将服务的逻辑封装在一个单独的类中,然后从“运行器”类开始。该运行器类可以是实际的服务,也可以只是控制台应用程序。因此,您的解决方案有(至少)3个项目:

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

1
我也曾经使用过这种方法,但是我认为将这种方法与上面的答案结合使用是一种享受。
罗布

27

Fabio Scopel的这段YouTube视频解释了如何很好地调试Windows服务...视频中的实际方法从4:45开始...

这是视频中解释的代码...,在Program.cs文件中,为“调试”部分添加内容...

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

        }
    }
}

在Service1.cs文件中,添加OnDebug()方法。

    public Service1()
    {
        InitializeComponent();
    }

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

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

    protected override void OnStop()
    {
    }

怎么运行的

基本上,您必须创建一个public void OnDebug()调用,OnStart(string[] args)因为它受保护并且无法在外部访问。该void Main()程序通过加上#if预处理器#DEBUG

Visual Studio定义DEBUG项目是否以Debug模式编译。这将在条件为true时执行下面的debug部分

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

它会像控制台应用程序一样运行,一旦一切正常,您可以更改模式Release,常规else部分将触发逻辑


我一直在寻找这个答案,不知道为什么它排名如此之低。解释了代码以帮助他人或可能有更多评论;)
Vinod Srivastav '18

14

更新

到目前为止,这种方法是最简单的:

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

为了后代,我在下面保留原始答案。


我的服务倾向于有一个封装了Timer的类,因为我希望该服务定期检查是否有任何工作要做。

在服务启动期间,我们将新建类并调用StartEventLoop()。(也可以从控制台应用程序轻松使用此类。)

这种设计的一个很好的副作用是,用来设置Timer的参数可以在服务真正开始工作之前有一个延迟,这样您就有时间手动附加调试器。

ps 如何将调试器手动附加到正在运行的进程...?

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

我也曾经做过以下事情(已经在前面的答案中提到过,但是使用条件编译器[#if]标志来帮助避免在Release版本中触发)。

我停止这样做是因为有时我们会忘记在Release中进行构建,而在客户端演示上运行的应用程序中出现调试器中断(令人尴尬!)。

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

如果// do something需要30分钟以上才能完成?
Vinod Srivastav '18

13

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
}

[对不起,代码没有解释-降价问题]应该在调试版本中从MS Visual Studio(F5)正常运行。仍在发行版中作为常规服务运行。
Thomas Bratt

将此与Christian K.的上述解决方案结合使用,以使用“ Environment.UserInteractive”属性,该解决方案确实干净,简单。
本·罗宾斯

OnStartprotected,您无法修改访问级别:(
爱德华·卢卡

10

您也可以通过命令提示符(sc.exe)启动服务。

就个人而言,我将在调试阶段将代码作为独立程序运行,并且当大多数错误被消除后,更改为作为服务运行。


10

我曾经做过的事情是拥有一个命令行开关,它将以服务或常规应用程序的形式启动程序。然后,在我的IDE中设置开关,以便逐步执行代码。

使用某些语言,您实际上可以检测它是否在IDE中运行,并自动执行此切换。

您使用什么语言?


9

使用TopShelf库。

创建一个控制台应用程序,然后在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()
        {

        }
    }

要调试服务,只需在Visual Studio中按F5。

要安装服务,请输入cmd“ console.exe install”

然后,您可以在Windows服务管理器中启动和停止服务。


他们的许可过于混乱,无法理解
l --''''''---------''''''''''

他们使用Apache License afaik。Topshelf是我用来开发和调试Windows服务的最简单方法。超级好用。开发为控制台应用程序。使用一个命令行开关作为服务安装。强烈推荐。
抢劫

TopShelf节省了我很多时间。Thx
L_7337,19年

8

我认为这取决于您所使用的操作系统,由于会话之间的分隔,Vista很难附加到服务上。

我过去使用的两个选项是:

  • 使用GFlags(在Windows调试工具中)为进程设置永久调试器。它存在于“图像文件执行选项”注册表项中,并且非常有用。我认为您需要调整服务设置以启用“与桌面交互”。我将其用于所有类型的调试,而不仅仅是服务。
  • 另一个选择是将代码分开一点,以便服务部分可与常规应用程序启动互换。这样,您可以使用简单的命令行标志,并将其作为进程(而不是服务)启动,这使得调试变得更加容易。

希望这可以帮助。


GFlags +1。如果您无法修改源代码(或没有源代码),则此功能特别有用。
克里斯·吉伦

6

我希望能够调试服务的各个方面,包括OnStart()中的任何初始化,同时仍在SCM框架内以完整的服务行为执行它,而无需“控制台”或“应用程序”模式。

为此,我在同一项目中创建了第二个服务以用于调试。调试服务正常启动时(即在服务MMC插件中),将创建服务主机进程。即使您尚未启动真正的服务,这也可以为您提供一个将调试器附加到其中的过程。将调试器附加到进程后,启动您的真实服务,您可以在服务生命周期中的任何位置(包括OnStart())进入它。

由于调试服务所需的代码入侵极少,因此调试服务可以轻松地包含在服务设置项目中,并且可以通过注释掉一行代码并删除单个项目安装程序而轻松地从生产版本中删除。

细节:

1)假设您正在实施MyService,请同时创建MyServiceDebug。将两者都添加到ServiceBase数组中,Program.cs如下所示:

    /// <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)将真实服务和调试服务添加到服务项目的项目安装程序中:

在此处输入图片说明

当您将服务项目输出添加到该服务的安装项目时,将同时包含这两个服务(真实和调试)。安装后,这两个服务都将出现在service.msc MMC插件中。

3)在MMC中启动调试服务。

4)在Visual Studio中,将调试器附加到调试服务启动的进程。

5)启动真正的服务,享受调试。


5

当我编写服务时,我将所有服务逻辑放入一个dll项目中,并创建两个调用该dll的“主机”,一个是Windows服务,另一个是命令行应用程序。

我使用命令行应用程序进行调试,并将调试器仅附加到真实服务中,以解决无法在命令行应用程序中重现的错误。

我使用这种方法时,只是记得必须在真实服务中运行时测试所有代码,而命令行工具是一个很好的调试辅助工具,它是一个不同的环境,它的行为并不完全类似于真实服务。


4

在开发和调试Windows服务时,我通常通过添加/ console启动参数并进行检查来将其作为控制台应用程序运行。使生活更加轻松。

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

直到您必须调试服务特定的问题。
leppie

是的,那么您必须将调试器附加到实际的服务过程。但是在大多数情况下,错误都会以两种方式出现,并且开发容易得多。
莫里斯


2

为了调试Windows服务,我将GFlags和regedit创建的.reg文件结合在一起。

  1. 运行GFlags,指定exe名称和vsjitdebugger
  2. 运行regedit并转到GFlags设置其选项的位置
  3. 从文件菜单中选择“导出密钥”
  4. 使用.reg扩展名将该文件保存到某处
  5. 任何时候您要调试服务:双击.reg文件
  6. 如果要停止调试,请双击第二个.reg文件。

或保存以下代码片段,并将servicename.exe替换为所需的可执行文件名称。


debugon.reg:

Windows注册表编辑器版本5.00

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Image File Execution Options \ servicename.exe]
“ GlobalFlag” =“ 0x00000000”
“调试器” =“ vsjitdebugger.exe”

debugoff.reg:

Windows注册表编辑器版本5.00

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

在Win 7 / Win 2008上仍然可以使用吗?这是来自support.microsoft.com/kb/824344的方法,但它依赖于交互式服务,我认为它们被杀死了吗?它始终是我的首选选项(因为启动问题可能会在生产中出现,因此在代码中插入Debugger.Break()可能不是一种选择)。
piers7 2010年

1

对于常规的小型编程,我做了一个非常简单的技巧来轻松调试我的服务:

服务启动时,我检查命令行参数“ / debug”。如果使用此参数调用该服务,则我不执行通常的服务启动,而是启动所有侦听器,仅显示一个消息框“调试正在进行中,按OK结束”。

因此,如果我的服务以通常的方式启动,它将作为服务启动,如果使用命令行参数/ debug启动,它将像普通程序一样工作。

在VS中,我将添加/ debug作为调试参数,然后直接启动服务程序。

这样,我可以轻松调试大多数小型问题。当然,仍然需要将某些东西调试为服务,但是对于99%的用户来说,这已经足够了。



1

我在JOP的答案上使用了变体。使用命令行参数,可以在IDE中使用项目属性或通过Windows服务管理器来设置调试模式。

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


1

只需将调试器放到任何地方吃午餐,然后在启动时附加Visualstudio

#if DEBUG
    Debugger.Launch();
#endif

你也需要开始为VS和Administatrator你需要允许,进程可以自动被指出错误的用户进行调试(如解释在这里):

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


1

这是我用来测试服务的简单方法,没有任何其他“调试”方法,并且集成了VS单元测试。

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

这比较容易。只需将解决方案配置设置更改为调试,然后运行项目/解决方案,然后添加断点即可。
巴哈姆特

0

您有两个选择可以进行调试。

  1. 创建一个日志文件:我个人更喜欢像文本文件这样的单独的日志文件而不是使用应用程序日志或事件日志。但这会花费很多时间,因为它仍然很难弄清我们确切的错误位置在哪里。
  2. 将应用程序转换为控制台应用程序:这将为您提供我们可以在VS中使用的所有调试工具。

请参考博客文章,我为创建过主题。


0

只是粘贴

Debugger.Break();

您代码中的任何位置。

例如 ,

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

Debugger.Break();当您运行程序时,它将命中。


0

最好的选择是使用“ System.Diagnostics ”命名空间。

如下所示,将代码封装在if else块中,以用于调试模式和发布模式,以在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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.