【问题标题】:Easiest way to develop/debug a Windows service开发/调试 Windows 服务的最简单方法
【发布时间】:2010-11-10 19:40:44
【问题描述】:

我正在 VB.NET 2008 中开发一个 Windows 服务,但我觉得我会得动脉瘤。为了调试服务,我在初始化代码中添加了 15 秒的等待时间,这让我有时间在任何事情发生之前启动服务并附加 .NET 调试器,这样我就可以打断点等。我真的很怀念这种解决方法的“集成”调试,而且测试似乎是一个巨大的痛苦。

对正在开发的 Windows 服务进行“常规”调试的最佳方法是什么?我考虑过的一个选择是将我的所有逻辑移动到一个 DLL 项目中,只在服务本身中保留控制逻辑,然后创建一个基本上只有“开始”和“停止”按钮的 Forms 项目,并调用DLL 执行其他所有操作。这样,我就可以正常调试我的代码,然后在 DLL 准备好时部署编译好的服务。

这有意义/惹恼其他人吗?我愿意接受任何可用的解决方法。 PB 的建议here 听起来就像我在问的那样——有人用过这种方法吗?

【问题讨论】:

  • 他们应该在医院为程序员开设一个动脉瘤病房。我会和你一起去那里。

标签: .net vb.net debugging windows-services


【解决方案1】:

如果你能处理一点 C#,我就是这样做的。

假设你有一个从 ServiceBase 派生的 MainService 类,带有 onStart 方法,那么当不在调试器中运行时,服务正常启动,否则手动调用 onStart 以控制台模式运行代码。

static void Main(string[] args)
{
       // If no command line arguments, then run as a service unless we are debugging it.
       if ( args.Length == 0) 
       {
            if (System.Diagnostics.Debugger.IsAttached)
            {
                 System.Diagnostics.Debugger.Break();
                 args = new string[] { "/NonService"} ;
            }
          else
                 args = new string[] { "/Service"} ;
       }

       string cmdLine = args[0].ToLower().Substring(1);
       Console.WriteLine("Starting Program with Cmdline : " + args[0]);
       switch (cmdLine)
       {
           case "service" :
               ServiceBase.Run(new MainService());
               break;

           case "nonservice" :
               MainService ms = new MainService();
               ms.OnStart(null);
               break;

         ...

         default :
            Console.Error.WriteLine("Unknown Command line Parameter");
            Console.Error.WriteLine("Supported options are /Install /Uninstall /Start /Stop /Status /Service and /NonService");
         }

【讨论】:

  • 项目属性中的“输出类型”是什么? “控制台应用程序”?
  • 是的,它是控制台应用程序。
  • +1 - 基本上唯一的方法是在开发/调试期间不提供服务,并从命令行应用程序中取消它。服务本身调试起来很痛苦。
【解决方案2】:

除了使用其他几个人已经提到的 Debugger.Break() 之外,我将我所有的服务代码都写在一个单独的程序集中,用于实际的 Windows 服务项目本身。然后我还编写了一个调用相同服务代码的 Windows 控制台应用程序。这让我只需将控制台应用程序设置为启动项目即可在 IDE 中进行调试。

Windows 服务项目和 Windows 控制台应用程序本身实际上除了调用服务“核心”代码之外什么都不做,因此由于服务和控制台应用程序之间的差异导致的缺陷范围很小。

【讨论】:

    【解决方案3】:
    Debugger.Break()  
    

    :)

    【讨论】:

    • 显然,我只是需要其他人来分享这个想法是有效的。它就像一个魅力,并且看起来并不比常规调试器慢。
    • 嗯,也许我的头很厚?我将 Debugger.Break() 添加为 OnStart() 的第一行,然后启动服务。现在我得到一个进度条,说它正在开始。然后在 VS 中附加到进程 - 它已列出但显示为灰色,我无法附加调试器。我错过了什么吗?
    【解决方案4】:

    当我使用 .NET 开发 Windows 服务时,我利用了单元测试和 TypeMock,以便我可以在单元测试中运行服务的代码,而无需附加到正在运行的服务实例。您可以查看的其他模拟框架包括 Rhino Mocks

    所以我的计划是使用 MSTest 创建针对我的服务运行的单元测试项目和测试方法,并且任何运行时依赖项都将由 TypeMock 处理,TypeMock 将创建模拟对象供我的服务使用。因此,例如,如果我的服务正在处理与文件有关的东西,那么我可以使用 TypeMock 创建一个模拟文件,并在我的单元测试中使用它来传递给服务。

    过去,我经历了编译、安装、运行和附加等服务的痛苦。当我发现模拟框架时,能够一键测试我的代码的感觉真是太棒了Visual Studio IDE 中的一个按钮。

    试一试。

    【讨论】:

      【解决方案5】:

      另一种方法是转到 service1.designer.vb 文件,找到并“封装”以下方法代码,如下所示:

      Shared Sub Main()
      #If DEBUG Then
         Dim servicio As New Service1
         servicio.OnStart(Nothing)
         System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite)
      #Else
         Dim ServicesToRun() As System.ServiceProcess.ServiceBase               'original code
         ServicesToRun = New System.ServiceProcess.ServiceBase() {New Service1} 'original code
         System.ServiceProcess.ServiceBase.Run(ServicesToRun)                   'original code
      #End If
      

      希望对那些使用遗留代码的程序员有所帮助;) 归功于一位程序员同事,他教给了我。

      【讨论】:

        【解决方案6】:

        我已经构建了一个 WCF 服务,它作为带有 .EXE 扩展名的命令行应用程序执行。这使我只需双击它即可在调试或 VS 外部轻松加载应用程序。然后我有另一个项目,它是一个 Windows 服务主机,并引用了我的 WCF 服务项目。 Host Service 可以像处理 .dll 文件一样处理 .exe 文件。

        这可能存在我没有遇到过的问题,因此我不能将其推荐为“最佳做法”,但它对我来说效果很好,并且可以解决您正在处理的问题。

        【讨论】:

        • 您可以使用单个 .exe 和命令行选项来执行此操作。如果作为控制台应用程序启动,启动线程调用Service.Start(),等待按键(或其他)然后调用Service.Stop()。因此几乎可以调试所有代码。
        【解决方案7】:

        我将 Windows 服务编写为控制台应用程序,然后将初始化代码从 Main 移动到 Service_Start 命令。这适用于大多数服务。您仍然可以通过控制台应用程序测试服务的停止/启动功能。

        【讨论】:

          【解决方案8】:

          就像leppie和其他人所说的,包括PB's suggestion,使用:

          Debugger.Break()
          

          但也请记住,一旦您的服务运行,您可以将 VS.NET 附加到正在运行的服务进程并设置断点。当然,如果断点处的代码自动命中,则需要快速附加,但在我的情况下,我的服务处理请求,所以我附加到服务并触发请求。

          【讨论】:

            【解决方案9】:

            阅读Debugging a .Net Windows Service the "easy way"。在本文中,Mark Pearce 描述了如何从 Visual Studio 调试 .Net Windows 服务。基本上它归结为以下代码 sn-p,但请阅读文章以获取完整解决方案。

            Shared Sub Main()
            #If DEBUG Then
                Dim DebugService As New ServiceAdmin
                DebugService.OnStart(Nothing)
            #Else
                Dim ServicesToRun() As System.ServiceProcess.ServiceBase
                ServicesToRun = New System.ServiceProcess.ServiceBase() {New ServiceAdmin()}
                System.ServiceProcess.ServiceBase.Run(ServicesToRun)
            #End If
            End Sub
            

            【讨论】:

            • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
            猜你喜欢
            • 2023-03-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多