簡體   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