开发/调试Windows服务的最简单方法

时间:2009-07-14 21:28:58

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

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

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

这是否有意义/惹恼别人?我愿意接受任何可用的解决方法。 PB的建议here听起来就像我问的那样 - 是否有人使用过这种方法?

9 个答案:

答案 0 :(得分:13)

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

假设你有一个使用onStart方法派生自ServiceBase的类MainService,那么当没有在调试器内运行时,服务会正常启动,否则会手动调用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 :(得分:11)

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

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

答案 2 :(得分:8)

Debugger.Break()  

:)

答案 3 :(得分:6)

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

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

在过去,我经历了编译服务,安装,运行和附加等的痛苦。当我发现模拟框架时,只需单击一下即可测试我的代码是一种很棒的感觉。 Visual Studio IDE中的一个按钮。

试一试。

答案 4 :(得分:3)

另一种方法是转到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

希望对那些有遗留代码的程序员提供帮助;) 积分给了一个程序员,他把它教给我。

答案 5 :(得分:2)

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

这可能会有一些我没有遇到过的问题所以我不能推荐它作为“最佳实践”,但它对我来说非常有效,并且解决了你正在处理的问题。

答案 6 :(得分:2)

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

答案 7 :(得分:1)

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

Debugger.Break()

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

答案 8 :(得分:-1)

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

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
相关问题