是否有比通过Windows服务控制管理器启动服务,然后将调试器附加到线程更简单的方法来逐步遍历代码?这有点麻烦,我想知道是否有更直接的方法。
当前回答
当我写一个服务时,我把所有的服务逻辑都放在一个dll项目中,并创建了两个“主机”来调用这个dll,一个是Windows服务,另一个是命令行应用程序。
我使用命令行应用程序进行调试,并仅针对无法在命令行应用程序中重现的错误将调试器附加到实际服务。
如果您使用这种方法,请记住,您必须在实际服务中运行时测试所有代码,而命令行工具是一个很好的调试辅助工具,它是一个不同的环境,并且它的行为与实际服务不完全相同。
其他回答
static void Main()
{
#if DEBUG
// Run as interactive exe in debug mode to allow easy
// debugging.
var service = new MyService();
service.OnStart(null);
// Sleep the main thread indefinitely while the service code
// runs in .OnStart
Thread.Sleep(Timeout.Infinite);
#else
// Run normally as service in release mode.
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]{ new MyService() };
ServiceBase.Run(ServicesToRun);
#endif
}
第一行的Debugger.Break()怎么样?
有时,分析在服务启动期间发生了什么是很重要的。附加到流程在这里没有帮助,因为在服务启动时附加调试器的速度不够快。
简单的回答是,我使用以下4行代码来做到这一点:
#if DEBUG
base.RequestAdditionalTime(600000); // 600*1000ms = 10 minutes timeout
Debugger.Launch(); // launch and attach debugger
#endif
这些被插入到服务的OnStart方法中,如下所示:
protected override void OnStart(string[] args)
{
#if DEBUG
base.RequestAdditionalTime(600000); // 10 minutes timeout for startup
Debugger.Launch(); // launch and attach debugger
#endif
MyInitOnstart(); // my individual initialization code for the service
// allow the base class to perform any work it needs to do
base.OnStart(args);
}
对于那些以前没有做过的人,我在下面列出了详细的提示,因为你很容易陷入困境。以下提示适用于Windows 7x64和Visual Studio 2010 Team Edition,但也适用于其他(更新的)环境。
重要提示:以“手动”模式部署服务(在VS命令提示符中使用InstallUtil实用程序或运行您准备好的服务安装程序项目)。在启动服务之前打开Visual Studio并加载包含服务源代码的解决方案——在Visual Studio中根据需要设置额外的断点——然后通过服务控制面板启动服务。
因为调试器。启动代码,这将导致一个对话框“一个未处理的Microsoft . net Framework异常发生在Servicename.exe.”出现。单击“是”,调试Servicename.exe,如下图所示:
之后,Windows UAC可能会提示您输入管理凭据。输入它们并继续执行Yes:
之后,著名的Visual Studio即时调试器窗口出现。它询问您是否要使用已删除的调试器进行调试。在单击Yes之前,选择不想打开新实例(第二个选项)——在这里,新实例没有帮助,因为不会显示源代码。所以你选择之前打开的Visual Studio实例:
单击Yes后,过一会儿Visual Studio将在调试器所在的行中显示黄色箭头。启动语句,您可以调试您的代码(方法MyInitOnStart,其中包含初始化)。
按F5继续立即执行,直到到达您准备的下一个断点。
提示:要保持服务运行,请选择Debug -> Detach all。这允许您在服务正确启动并完成调试启动代码之后运行与服务通信的客户机。如果您按下Shift+F5(停止调试),这将终止服务。您应该使用服务控制面板来停止它,而不是这样做。
请注意,
If you build a Release, then the debug code is automatically removed and the service runs normally. I am using Debugger.Launch(), which starts and attaches a debugger. I have tested Debugger.Break() as well, which did not work, because there is no debugger attached on start up of the service yet (causing the "Error 1067: The process terminated unexpectedly."). RequestAdditionalTime sets a longer timeout for the startup of the service (it is not delaying the code itself, but will immediately continue with the Debugger.Launch statement). Otherwise the default timeout for starting the service is too short and starting the service fails if you don't call base.Onstart(args) quickly enough from the debugger. Practically, a timeout of 10 minutes avoids that you see the message "the service did not respond..." immediately after the debugger is started. Once you get used to it, this method is very easy because it just requires you to add 4 lines to an existing service code, allowing you quickly to gain control and debug.
下面是我用来测试服务的简单方法,没有任何额外的“调试”方法,并带有集成的VS单元测试。
[TestMethod]
public void TestMyService()
{
MyService fs = new MyService();
var OnStart = fs.GetType().BaseType.GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
OnStart.Invoke(fs, new object[] { null });
}
// As an extension method
public static void Start(this ServiceBase service, List<string> parameters)
{
string[] par = parameters == null ? null : parameters.ToArray();
var OnStart = service.GetType().GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
OnStart.Invoke(service, new object[] { par });
}
使用TopShelf库。
创建一个控制台应用程序,然后在Main中配置安装
class Program
{
static void Main(string[] args)
{
HostFactory.Run(x =>
{
// setup service start and stop.
x.Service<Controller>(s =>
{
s.ConstructUsing(name => new Controller());
s.WhenStarted(controller => controller.Start());
s.WhenStopped(controller => controller.Stop());
});
// setup recovery here
x.EnableServiceRecovery(rc =>
{
rc.RestartService(delayInMinutes: 0);
rc.SetResetPeriod(days: 0);
});
x.RunAsLocalSystem();
});
}
}
public class Controller
{
public void Start()
{
}
public void Stop()
{
}
}
要调试您的服务,只需在visual studio中按F5。
要安装服务,键入cmd "console.exe install"
然后,您可以在windows服务管理器中启动和停止服务。
推荐文章
- 为什么Android工作室说“等待调试器”如果我不调试?
- Linq-to-Entities Join vs GroupJoin
- 为什么字符串类型的默认值是null而不是空字符串?
- 在list中获取不同值的列表
- 组合框:向项目添加文本和值(无绑定源)
- 在Windows批处理脚本中格式化日期和时间
- AutoMapper:“忽略剩下的?”
- 如何为ASP.net/C#应用程序配置文件值中的值添加&号
- 映射一个网络驱动器供服务使用
- 从System.Drawing.Bitmap中加载WPF BitmapImage
- 如何找出一个文件存在于c# / .NET?
- 如何在windows中使用命令提示符(cmd)列出文件。我试过在Linux中使用“ls”,但它显示一个错误?
- 为什么更快地检查字典是否包含键,而不是捕捉异常,以防它不?
- [DataContract]的命名空间
- string. isnullorempty (string) vs. string. isnullowhitespace (string)