[英]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.