如何从 Visual Studio 运行 Windows 服务项目。
我正在 Visual Studio 2008 中构建 Windows 服务,我必须始终从控制面板运行该服务,然后将调试器附加到正在运行的服务实例。这有点烦人,因为我正在清理大量代码,并且在开发过程中需要多次重新启动我的服务。
我想设置我的项目以便能够按 F5 并运行服务并直接进入调试模式。关于如何实现这一目标的一些提示会很棒。
提前致谢!
从这里复制。
static void Main(string[] args)
{
DemoService service = new DemoService();
if (Environment.UserInteractive)
{
service.OnStart(args);
Console.WriteLine("Press any key to stop program");
Console.Read();
service.OnStop();
}
else
{
ServiceBase.Run(service);
}
}
这应该允许您从 Visual Studio 中运行。
另一种方法是通过调用
System.Diagnostics.Debugger.Break()
在代码中嵌入编程断点。当您将其放置在服务的 OnStart() 回调中并从服务控制台启动服务时,编程断点将触发一个对话框,允许您附加到 Visual Studio 的现有实例或启动新的实例。实例。这实际上是我用来调试服务的机制。
在您的
Main()
例程中检查 Debugger.IsAttached
,如果为真,则像控制台一样启动您的应用程序,如果不是,请调用 ServiceBase.Run()
。
可以为作为控制台应用程序运行的 Windows 服务设置一个配套项目,但使用反射访问服务方法。有关详细信息和示例,请参阅此处:http://ryan.kohn.ca/articles/how-to-debug-a-windows-service-in-csharp-using-reflection/.
以下是您在控制台应用程序中需要的相关代码:
using System;
using System.Reflection;
namespace TestableWindowsService
{
class TestProgram
{
static void Main()
{
Service1 service = new Service1();
Type service1Type = typeof (Service1);
MethodInfo onStart = service1Type.GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Instance); //retrieve the OnStart method so it can be called from here
onStart.Invoke(service, new object[] {null}); //call the OnStart method
}
}
}
您也可以这样做:(请参阅评论以获取解释)
public class Program : ServiceBase
{
private ServiceHost _serviceHost = null;
public Program()
{
ServiceName = "";
}
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
#if(!DEBUG)
// when deployed(built on release Configuration) to machine as windows service use this
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new Program() };
ServiceBase.Run(ServicesToRun);
#else
// when debugging use this (When debugging after building in Debug Configuration)
//If you want the DEBUG preprocessor constant in Release you will have to check it on in the project configuration
Program progsvc = new Program();
progsvc.OnStart(new string[] { });
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#endif
}
protected override void OnStart(string[] args)
{
// Start Web Service
if (_serviceHost != null)
{
_serviceHost.Close();
}
_serviceHost = new ServiceHost(typeof(Namespace.Service));
_serviceHost.Open();
}
}
创建一个单独的项目,仅引用服务项目并实例化和启动服务。它就像普通应用程序一样运行,您可以进入其中。
YourService s = new YourService();
s.Start();
只需从服务构造函数中调用 OnStart() 事件
我是按照以下方式做的
public XXX()
{
InitializeComponent();
OnStart(new string[] { "shafi", "moshy" });
}
您希望将 Windows 服务作为 shell,其中应该有很少的代码,这样您就不必测试它。
您应该在课堂上拥有您希望服务完成的所有事情。
您可以对您的课程进行单元测试,如果有效,则将其引用到您的服务。
这样,当你让你的班级做你想做的每件事时,那么当它应用于你的服务时,每件事都应该有效。 :)
通过事件日志,您可以看到服务在运行时正在做什么,这也是一个很好的测试方法:D 尝试一下。
namespace WindowsService
{
public partial class MyService : ServiceBase
{
public MyEmailService()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("MySource")) // Log every event
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog"); // Create event source can view in Server explorer
}
eventLogEmail.Source = "MySource";
eventLogEmail.Log = "MyNewLog";
clsRetriveEmail Emails = new clsRetriveEmail();
eventLogEmail.WriteEntry("Populateing database with mail"); // log event
Emails.EmailGetList(); // Call class
}
protected override void OnStart(string[] args)
{
eventLogEmail.WriteEntry("Started");
}
protected override void OnStop()
{
eventLogEmail.WriteEntry("Stopped");
}
protected override void OnContinue()
{
eventLogEmail.WriteEntry("Continuing");
}
}
}
这些链接在使用服务时非常有帮助。
这是创建它们的一个过程 http://msdn.microsoft.com/en-us/library/zt39148a.aspx
James Michael Hare 在他的博客 http://geekswithblogs.net/BlackRabbitCoder/ 上写了一篇关于他制作的非常好的模板/框架的文章,使开发(和调试)Windows 服务变得更加容易:C# 工具箱:可调试的、自安装 Windows 服务模板(2 中的 1)http://geekswithblogs.net/BlackRabbitCoder/archive/2010/09/23/c-windows-services-1-of-2-creating-a-debuggable-windows .aspx
它为您提供快速入门所需的所有基础知识。最重要的是,它为您提供了一种非常好的调试服务的方法,就像它是常规控制台应用程序一样。我还可以提到它提供了开箱即用的功能来安装(和卸载)您的服务。帖子的第二部分可以在此链接中找到。
我自己用过几次,真的可以推荐它。
13 年后,有了最新的 C# .NET Core 等。我尝试了 Matt Davis(保护访问级别问题)和 Ryan Kohn(传递参数问题,也无法通过反射调用
OnStart
)的解决方案,但没有成功。最后我通过小小的调整就完成了,我认为这可能是一个更好的方法。
在您的服务中添加
Start
功能:
public partial class MyService : ServiceBase {
public void Start(string[] args = null)
{
OnStart(args);
}
}
在
Main
中,像这样使用它,不需要任何反射:
static void Main(string[] args)
{
MyService service = new MyService ();
if (Environment.UserInteractive)
{
service.Start(args);
if (!Debugger.IsAttached)
{
Console.WriteLine("Press any key to stop program");
Console.Read();
service.Stop();
Environment.Exit(0);
}
}
else
{
ServiceBase.Run(service);
}
}
您可以在可视化代码调试模式下或作为常规 CLI 命令运行该服务。不同之处在于,当您在 VScode 中点击“停止调试”时,
OnStop
代码不会被执行。