[英]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
指令來更改代碼,而是簡單地:
使用 VS 的連接到進程對話框連接到正在運行的進程
享受。
這樣做的好處是您不會更改代碼,因此它與您的生產二進制文件完全相同,我認為這很重要。
祝你好運。
要在不安裝服務的情況下調試或測試您的服務,請像這樣在 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.