繁体   English   中英

调试 Windows 服务

[英]Debugging a Windows Service

我正在制作 Windows 服务,我想调试它。

这是我尝试调试它时遇到的错误:

无法从命令行或调试器启动服务。 必须先安装 Windows 服务,然后使用服务器资源管理器、Windows 服务管理 TOll 或 NET 启动命令启动。

我已经使用InstallUtil安装了我的服务,但我仍然面临问题。

此外,当我尝试附加进程时,我的服务进入运行模式,它永远不会开始调试。

编辑:每次我们进行更改或仅构建它时,我们是否必须重新安装 Windows 服务?

在您的OnStart中使用如下内容:

#if DEBUG
if(!System.Diagnostics.Debugger.IsAttached)
   System.Diagnostics.Debugger.Launch();
#endif

对于大多数用例,将服务作为控制台应用程序运行就足够了。 为此,我通常有以下启动代码:

private static void Main(string[] args) {
    if (Environment.UserInteractive) {
        Console.WriteLine("My Service");
        Console.WriteLine();
        switch (args.FirstOrDefault()) {
        case "/install":
            ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location});
            break;
        case "/uninstall":
            ManagedInstallerClass.InstallHelper(new[] {"/u", Assembly.GetExecutingAssembly().Location});
            break;
        case "/interactive":
            using (MyService service = new MyService(new ConsoleLogger())) {
                service.Start(args.Skip(1));
                Console.ReadLine();
                service.Stop();
            }
            break;
        default:
            Console.WriteLine("Supported arguments:");
            Console.WriteLine(" /install      Install the service");
            Console.WriteLine(" /uninstall    Uninstall the service");
            Console.WriteLine(" /interactive  Run the service interactively (on the console)");
            break;
        }
    } else {
        ServiceBase.Run(new MyService());
    }
}

这不仅使运行和调试服务变得容易,而且还可以在不需要 InstallUtil 程序的情况下安装和卸载。

这个问题在使服务成为控制台/服务混合方面有一个很好的答案。 请参阅用户 marc_s 的答案 我不想在这里重复答案。

就我个人而言,我发现最简单的解决方案不是通过添加更多的混乱和#if #else指令来更改代码,而是简单地:

  1. DEBUG模式下编译服务二进制文件
  2. 将安装的服务指向DEBUG二进制文件
  3. 运行服务
  4. 使用 VS 的连接到进程对话框连接到正在运行的进程连接到进程对话框

  5. 享受。

这样做的好处是您不会更改代码,因此它与您的生产二进制文件完全相同,我认为这很重要。

祝你好运。

要在不安装服务的情况下调试或测试您的服务,请像这样在 Program.cs 中进行更改。

static class Program
{
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
    { 
      new MyService() 
    };
        ServiceBase.Run(ServicesToRun);
    }
   }

将其更改为:

static class Program
{
static void Main()
{
    #if(!DEBUG)
       ServiceBase[] ServicesToRun;
       ServicesToRun = new ServiceBase[] 
   { 
        new MyService() 
   };
       ServiceBase.Run(ServicesToRun);
     #else
       MyService myServ = new MyService();
       myServ.Process();
       // here Process is my Service function
       // that will run when my service onstart is call
       // you need to call your own method or function name here instead of Process();
     #endif
    }
}

尝试遵循本指南

编辑:就个人而言,我在同一个项目中有一个控制台应用程序可以完成所有工作。 然后我让服务运行控制台应用程序的Main 它使调试变得容易,尤其是在开发时。

我之前做过的一种方法是在服务启动方法中插入一个 Debugger.Break() 。 编译并安装服务。 当它启动时,它会中断并使用对话框打开调试,从那里你应该能够附加和调试。

Debugger.Launch 方法是一个好方法,但我更喜欢创建一个 class 进行处理并从服务中调用它,然后也可以从 win forms 应用程序中调用它。 例如:

class ProcessingManager
{

    public void Start()
    {
     //do processing
    }

    public void Stop()
    {
    //stop
    }
}

然后在您的服务/赢 forms 应用程序中只需创建一个处理 class 的实例作为成员变量,并在启动和停止时调用该方法。 它可以在服务中使用,或者带有启动和停止按钮的 win forms 应用程序,我发现这比每次都附加调试器要快得多,因为您可以将 windows 应用程序设置为默认启动并在处理中添加任何断点经理。

从服务代码中提取:

namespace Service
{
    public partial class Service : ServiceBase
    {
        #region Members

        private ProcessingManager m_ProcessingManager = null;

        #endregion Members

        #region Constructor

        /// <summary>
        /// Constructor
        /// </summary>
        public Service()
        {
            InitializeComponent();

            try
            {
                //Instantiate the processing manager
                m_ProcessingManager = new ProcessingManager();
            }
            catch (Exception ex)
            {
                ErrorHandler.LogError(ex);
            }
        }

        #endregion Constructor

        #region Events

        /// <summary>
        /// Starts the processing
        /// </summary>
        /// <param name="args">Parameters</param>
        protected override void OnStart(string[] args)
        {
            try
            {
                //Start the Processing
                m_ProcessingManager.Start();
            }
            catch (Exception ex)
            {
                ErrorHandler.LogError(ex);
            }
        }

        /// <summary>
        /// Service Stopped
        /// </summary>
        protected override void OnStop()
        {
            try
            {
                //Stop Processing
                m_ProcessingManager.Stop();
            }
            catch (Exception ex)
            {
                ErrorHandler.LogError(ex);
            }
        }

        #endregion Events
    }
}

我总是做的是:

#if DEBUG 

 Thread.Sleep(20000) 

#endif

OnStart中。 这给了我 20 多岁的时间来附加。

快速简单,只需记住将其包装在#if DEBUG #endif中即可:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM