【问题标题】:Debug Windows Service调试 Windows 服务
【发布时间】:2011-02-07 10:53:00
【问题描述】:

场景

我有一个用 C# 编写的 Windows 服务。 我已经阅读了所有关于如何调试它的谷歌线程,但我仍然无法让它工作。 我已经运行了“PathTo.NetFramework\InstallUtil.exe C:\MyService.exe”。它说安装成功,但是当我运行“Services.msc”时,该服务根本不显示,任何地方。如果我进入任务管理器,有一个名为“MyService.vshost.exe”的进程。很确定不是这样,因为它是服务,而不是流程。

谁能给我解释一下?

如果我应该在运行 Services.msc 时看到该服务? (请记住,这一切都是在本地机器上完成的,根本没有服务器。

其他

我正在运行 VS2008。

编辑:

这一切都在我的本地机器上完成,我没有服务器或访问任何服务器。 另外,我什至不知道服务做什么,我想调试它,以便我可以遍历代码并查看它是如何工作的(服务内部的代码,而不是服务本身 - 对于你们中的任何一个聪明的裤子可能建议我看一个模板)。

编辑 2:

这些都不起作用! 每次我尝试某些东西时,我都会收到一些关于必须使用 NET START 或安装服务的消息。

编辑 3:

我正在运行 VS2008。

我输入了这个: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe C:\dev\Restarter\bin\Release\Restarter.exe

我得到了这个: Microsoft (R) .NET Framework 安装实用程序版本 2.0.50727.3053 版权所有 (c) 微软公司。保留所有权利。

运行事务安装。

开始安装的安装阶段。 查看 C:\dev\Restarter\bin\ 的日志文件的内容 Release\Restarter.exe 程序集的进度。 该文件位于 C:\dev\Restarter\bin\Release\EDT.Restar 三、安装日志。 安装程序集“C:\dev\Restarter\bin\Release\Restarter.exe”。 受影响的参数是: 登录控制台 = 程序集路径 = C:\dev\Restarter\bin\Release\Restarter.exe 日志文件 = C:\dev\Restarter\bin\Release\Restarter.InstallLog

安装阶段成功完成,提交阶段开始。 查看 C:\dev\Restarter\bin\ 的日志文件的内容 Release\Restarter.exe 程序集的进度。 该文件位于 C:\dev\Restarter\bin\Release\Restar 三、安装日志。 提交程序集“C:\dev\Restarter\bin\Release\Restarter.exe”。 受影响的参数是: 登录控制台 = 程序集路径 = C:\dev\Restarter\bin\Release\Restarter.exe 日志文件 = C:\dev\Restarter\bin\Release\Restarter.InstallLog

提交阶段成功完成。

事务安装已完成。

C:\Program Files\Microsoft Visual Studio 9.0\VC>

然后我去了 RUN -> Services.msc 里面什么也看不见。

任务管理器中有一个名为“Restarter.vshost.exe”的进程。

就是这样。

我只想安装和调试它。 我知道它有效(因为它运行并且不会崩溃)。 但是代码是朋友写的,我想通过调试模式来了解底层代码。

【问题讨论】:

  • 您尝试调试部署/安装或运行时问题?
  • 您的编辑令人困惑。听起来您的第一个问题是让服务运行。请发布您用于安装服务的确切命令行以及响应。
  • 您是否尝试过使用 sc.exe 创建新服务?格式应该类似于:sc create NameToGiveTheService binPath=PathToExe。不确定您是否需要使用托管服务来执行此操作。 support.microsoft.com/kb/251192。它应该出现在服务列表中。

标签: c# windows-services debugging


【解决方案1】:

我推荐以下模式进行调试:

 var ServiceToRun = new SomeService(); 
 if (Environment.UserInteractive)
 {
    // This used to run the service as a console (development phase only)

    ServiceToRun.Start();

    Console.WriteLine("Press Enter to terminate ...");
    Console.ReadLine();

    ServiceToRun.DoStop();
 }
 else
 {
    ServiceBase.Run(ServiceToRun);
 }

编辑:确保您的目标是控制台应用程序,而不是 Windows 应用程序,否则它将无法工作。

【讨论】:

  • 那很好,我以前是使用#define X#if X 来控制作为服务运行而不是作为控制台应用运行,这绝对更优雅、更简洁。我希望我能再投票几次。
  • +1 我的服务没有 .Start 方法,所以我添加了 1。希望这不是我错过的东西
  • 控制台不显示,立即触发Stop()。
  • @guiomie 一步一步调试它,它不应该是这样,要么控制台应该打开,要么它作为服务运行直到终止。
  • @Andrey 我不得不将项目属性从 Windows 应用程序修改为控制台应用程序,然后它就起作用了。
【解决方案2】:

您可以通过将调试器附加到进程来对其进行调试。您可以通过在程序的启动中添加一行来做到这一点:

Debugger.Launch ();

添加 using 语句后:

using System.Diagnostics; 

您要么需要将其放入条件块中,要么在完成调试后将其删除

或通过运行服务,然后从 IDE 手动附加到进程:调试->附加到进程..

【讨论】:

  • 这对我来说是一个了不起的发现,我建议每个人都使用它,但有一个问题。您需要在推出之前将其删除,因此我建议将其包装在 if #DEBUG #endif... 中,前提是您在发行版中推出 :)
  • 我将此方法与在运行时提供参数结合使用(通过服务控制管理器 -> 右键单击​​ -> 属性 -> 常规选项卡 -> 启动参数)。您可以使用if (args != null && args.Any(s => s == Debugcommand)) System.Diagnostics.Debugger.Launch(); 检查参数值(例如在OnStart 中)。如果您不提供“启动参数”,那么您的服务将在不中断调试器的情况下运行,因此无需#ifdef。
  • 在使用此方法时,我仍然收到无法调试 Windows 服务的错​​误,即使将输出更改为控制台应用程序也是如此。
【解决方案3】:

我们可以让windows服务项目可调试,只需添加一个参数并使其表现得像一个控制台应用程序。

1) 转到您的 Windows 服务项目属性 -> 调试 -> 启动选项 2)给出一个论点 - 控制台 3) 转到应用程序选项卡 -> 输出类型,将其更改为控制台应用程序 4) 在 Program.cs 中输入以下代码

static class Program
    {
        private static EventWaitHandle _waitHandle;
        private static Service1 _service;
                static void Main(string[] args)
        {
            bool runConsole = false;**

            foreach (string arg in args)
            {
                if (arg.ToLowerInvariant().Equals("-console"))
                {
                    runConsole = true;
                }
            }   

            _service = new Service1();
            if (runConsole)
            {
                _waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
                Console.WriteLine("Starting Workflow Service in Console Mode");
                Console.WriteLine("Press Ctrl+C to exit Console Mode");
               Console.CancelKeyPress += new ConsoleCancelEventHandler(OnCancelKeyPress);
                _service.InternalStart();
                WaitHandle.WaitAll(new WaitHandle[] { _waitHandle });
            }

            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                new Service1() 
            };
            ServiceBase.Run(ServicesToRun);
        }

        static void OnCancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            _service.InternalStop();
            _waitHandle.Set();
        }


    }

【讨论】:

  • 在您的 Service1.cs 文件中添加一个方法 internal void InternalStart() { OnStart(null); } 和一个停止方法 internal void InternalStop() { OnStop(); }
【解决方案4】:

这在开发/调试 Windows 服务时帮助了我很多:

http://windowsservicehelper.codeplex.com/

只需按 F5 即可调试。很容易。

Andrey 的方法也很不错。

【讨论】:

  • 最简单的调试windows服务的方法。
【解决方案5】:

为了能够在不部署的情况下调试我的服务,我总是这样写:

在您的 program.cs 文件中:

#if DEBUG
    MyService myService = new MyService();
    myService.OnDebug();
    System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[]
    {
        new MyService()
    };
    ServiceBase.Run(ServicesToRun);
#endif

在您的 MyService.cs 文件中:

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

* 注意 *:当您最终完成调试并准备部署服务时,您必须在“发布”模式下构建,否则该服务将不被视为服务。 p>

希望这会有所帮助。

【讨论】:

  • 这很好,但我发现第一个答案更好地测试了服务中的 OnStart() 和 OnStop() 方法。只要您将 Start() 和 DoStop() 方法添加到您的服务,然后由于 OnStart/OnStop 保护级别而从它们调用 OnStart 和 OnStop 覆盖。
【解决方案6】:

假设:

1) 您在 VS2008 IDE 的解决方案中拥有可用的源代码

我如何调试 C# 服务:

  1. 使用InstallUtil 安装服务。 (你好像已经这样做了)
  2. (如果需要)Change the Service path 到解决方案的 bin 文件夹中生成的 MyService.exe
  3. 在 Service 的 OnStart() 方法的开头添加如下内容:

    while(true)
    {
       System.Threading.Thread.Sleep(500);
    }
    
  4. System.Threading.Thread.Sleep(500)上设置断点

  5. 构建解决方案

  6. 使用Windows Service Utility启动您的服务

  7. 当您的服务启动时,在 VS2008 中转到 Debug -> Attach To Processes...

  8. 确保选中Show Processes From All UsersShow Processes In All Sessions

  9. 在列表中找到您的 MyService.exe,然后单击 Attach

  10. 您现在应该位于您在无限循环中插入的断点处

  11. 将控件(黄色箭头)拖到无限循环之外

  12. 调试吧!

免责声明:

当你想发布一个构建,或者当你只是想正常运行服务时,记得移除无限循环。

【讨论】:

  • 还要确保您的构建模式是“调试”并且步骤 2 的路径(在 Onion-Knight 的回答中)也指向 bin/Debug/YourService.exe
  • 嗨!但是VS2010不允许我把控件拖到循环外!
  • @ZoomIn 有 Run to CursorCtrl+Shift+F10 功能
【解决方案7】:

可能是服务名称不是您所期望的,这就是您找不到它的原因。服务名称在 .NET 项目的ServiceInstaller 属性中定义,不必以任何方式与可执行文件名称对应。但如果您确定安装后该服务未列出,您可以执行以下操作。

首先,服务安装。有两种方法,InstallUtil.exeSC.exe。第一个是专门为 .NET 服务定制的,因为它将运行所有 ProjectInstallerServiceInstaller 代码。第二个不会这样做,但它会给你更多的选择,通常更有效,即在InstallUtil 失败的地方可能会成功。这可能是在任何安装程序代码中存在异常时。

您已经尝试使用InstallUtil 进行安装,所以这里是SC 版本:

sc create MyService binPath= "C:\Service.exe"

请注意,MyService此时为服务指定的名称,它可以是您喜欢的任何名称(在合理范围内:-)。此名称将显示在服务控制台列表中。

安装服务后,您需要在调用OnStart 时对其进行调试。这可以通过从服务中运行并附加到调试器 (Visual Studio) 来实现:

protected override void OnStart(string[] args)
{
    #if DEBUG
    Debugger.Launch();
    #endif
    ...
}

不要忘记在此代码更改后构建和替换服务可执行文件。必须停止服务,但无需卸载并重新安装。

使用SC删除服务:

sc delete MyService

【讨论】:

    【解决方案8】:

    如果您的业务层与 Windows 服务分开,您可以在运行 Windows 服务之外测试您的所有业务功能。

    为了测试 Windows 服务,我喜欢创建一个作为控制台应用程序的测试项目,并启动一个新线程来运行我的服务。

    System.Threading.Thread sftpThread = new System.Threading.Thread((ThreadStart)service1);
    service1.Start();
    

    【讨论】:

      【解决方案9】:

      我最近将它添加到一个项目中,它对我来说非常有用。您可以像调试任何其他 EXE 一样对其进行调试。添加后,转到您的项目属性并在“调试”选项卡中为“调试”构建配置添加一个命令行参数 (/EXE)。

      <MTAThread()> _
      Shared Sub Main()
      
          '' 
          '' let's add a command line parameter so we can run this as a regular exe or as a service
          ''
          If Command().ToUpper() = "/EXE" Then
              Dim app As MyService = New MyService()
      
              app.OnStart(Nothing)
              Application.Run()
          Else
              Dim ServicesToRun() As System.ServiceProcess.ServiceBase
      
              ' More than one NT Service may run within the same process. To add
              ' another service to this process, change the following line to
              ' create a second service object. For example,
              '
              '   ServicesToRun = New System.ServiceProcess.ServiceBase () {New Service1, New MySecondUserService}
              '
              ServicesToRun = New System.ServiceProcess.ServiceBase() {New MyService}
      
              System.ServiceProcess.ServiceBase.Run(ServicesToRun)
          End If
      End Sub
      

      【讨论】:

        【解决方案10】:

        我建议在项目属性调试选项卡上添加/test 作为启动选项。然后,您无需安装即可运行您的服务。

        【讨论】:

          【解决方案11】:

          如果您使用 TopShelf 创建服务,您应该能够从 Visual Studio 轻松调试它

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-07-06
            • 2011-07-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多