C# 调试Windows服务

C# 调试Windows服务,c#,debugging,windows-services,C#,Debugging,Windows Services,我正在制作一个Windows服务,我想调试它 这是我尝试调试时遇到的错误: 无法从命令行或调试器启动服务。必须首先安装Windows服务,然后使用“服务器资源管理器”、“Windows服务管理”或“网络启动”命令启动该服务 我已经使用InstallUtil安装了我的服务,但是我仍然面临问题 另外,当我尝试附加进程时,我的服务进入运行模式,它永远不会开始调试 编辑:我们是否必须在每次进行更改时重新安装Windows服务,或者仅构建它就足够了?尝试以下操作 编辑:就我个人而言,我在同一个项目中有一个

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

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

无法从命令行或调试器启动服务。必须首先安装Windows服务,然后使用“服务器资源管理器”、“Windows服务管理”或“网络启动”命令启动该服务

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


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

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

尝试以下操作


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

我经常做的是:

#if DEBUG 

 Thread.Sleep(20000) 

#endif
OnStart
中。这给了我20多岁的时间


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

我以前做过的一种方法是在启动时的服务方法中插入调试器.Break()。编译并安装服务。当它启动时,断开并打开“调试方式”对话框,从那里您应该可以连接和调试。

启动中使用以下内容:

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

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

然后,在您的service/win forms应用程序中,只需创建处理类的实例作为成员变量,并在开始和停止时调用该方法。它可以在服务中使用,也可以在带有开始和停止按钮的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
    }
}
命名空间服务
{
公共部分类服务:ServiceBase
{
#区域成员
private ProcessingManager m_ProcessingManager=null;
#端区成员
#区域构造函数
/// 
///建造师
/// 
公共服务()
{
初始化组件();
尝试
{
//实例化处理管理器
m_ProcessingManager=新的ProcessingManager();
}
捕获(例外情况除外)
{
ErrorHandler.LogError(ex);
}
}
#端域构造函数
#地区活动
/// 
///开始处理
/// 
///参数
启动时受保护的覆盖无效(字符串[]args)
{
尝试
{
//开始处理
m_ProcessingManager.Start();
}
捕获(例外情况除外)
{
ErrorHandler.LogError(ex);
}
}
/// 
///服务停止
/// 
受保护的覆盖void OnStop()
{
尝试
{
//停止处理
m_ProcessingManager.Stop();
}
捕获(例外情况除外)
{
ErrorHandler.LogError(ex);
}
}
#端区事件
}
}

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

  • 在调试模式下编译服务二进制文件
  • 将已安装的服务指向调试二进制文件
  • 运行服务
  • 使用VS的“连接到进程”对话框连接到正在运行的进程

  • 享受

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


    祝你好运。

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

    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程序的情况下安装和卸载服务。

    在使服务成为控制台/服务的混合体方面有一个很好的答案。看。我不想在这里重复答案。

    要在不安装服务的情况下调试或测试服务,请在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
        }
    }
    

    不可能重复我以前见过上面的链接,但是没有任何东西对meDo有效,不仅仅是用其他网站的链接来回答。所以,这应该是一个一站式的解决方案来这里的人,而不是谷歌的代理。您始终可以添加或增强一些代码片段或信息。当我尝试附加进程时,我的服务进入运行模式,它从不开始调试。我这样做了:受保护的覆盖void OnStart(string[]args){if(DEBUG)Thread.Sleep(20000);}它给了我这个错误:名称“DEBUG”在当前上下文中不存在名称“Thread”在当前上下文中不存在DEBUG是一个预处理器语句,所以它应该是“#if DEBUG(do something)#endif”,确保您有#和{}“教授,我还是不明白。你能写一个示例代码吗?你能帮我做一下吗:我们是否每次进行更改都必须重新安装Windows服务,或者仅仅构建它就足够了?好的。我通常会做的是“安装”服务。要执行此操作,请打开visual studio命令行并键入“installutil servicename.exe”(servicename.exe将是编译的exe的完整路径),然后使您的服务在OS Services.msc控制台中可用。
    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
        }
    }