是否有比通过Windows服务控制管理器启动服务,然后将调试器附加到线程更简单的方法来逐步遍历代码?这有点麻烦,我想知道是否有更直接的方法。


当前回答

我喜欢能够调试我的服务的每个方面,包括在OnStart()中的任何初始化,同时仍然在SCM框架内执行完整的服务行为…没有“控制台”或“应用程序”模式。

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

因为调试服务只需要极少的代码侵入,所以可以很容易地将其包含在服务设置项目中,并且通过注释掉一行代码和删除单个项目安装程序就可以很容易地从产品版本中删除调试服务。

细节:

1)假设你正在实现MyService,也创建MyServiceDebug。将两者添加到Program.cs中的ServiceBase数组中,如下所示:

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

在将服务项目输出添加到服务的设置项目时,将包括两个服务(真实的和调试的)。安装后,这两个服务都将出现在服务中。MMC插件。

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

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

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

其他回答

对于现有Windows服务程序的故障排除,请像其他人建议的那样使用'Debugger.Break()'。

对于新的Windows服务程序,我建议使用James Michael Hare的方法http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable-windows-service-template-redux.aspx

这段YouTube视频由Fabio Scopel解释了如何调试一个Windows服务相当好…实际的方法从视频中的4:45开始…

下面是视频中解释的代码…在你的Program.cs文件中,添加Debug部分的东西…

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

它是如何工作的

基本上,你必须创建一个公共void OnDebug(),调用OnStart(string[] args),因为它是受保护的,不能在外部访问。void Main()程序添加了#if预处理器和#DEBUG。

如果项目在DEBUG模式下编译,Visual Studio定义DEBUG。这将允许调试部分(下面)在条件为真时执行

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

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

最好的选择是使用“系统”。诊断的名称空间。

将代码包含在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
#if DEBUG
    System.Diagnostics.Debugger.Break();
#endif

我认为这取决于你使用的操作系统,Vista很难附加到服务,因为会话之间的分离。

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

Use GFlags (in the Debugging Tools for Windows) to setup a permanent debugger for a process. This exists in the "Image File Execution Options" registry key and is incredibly useful. I think you'll need to tweak the Service settings to enable "Interact with Desktop". I use this for all types of debugging, not just services. The other option, is to separate the code a bit, so that the service part is interchangable with a normal app startup. That way, you can use a simple command line flag, and launch as a process (rather than a Service), which makes it much easier to debug.

希望这能有所帮助。