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