简体   繁体   English

将 Windows 服务作为控制台应用程序运行

[英]Run a Windows Service as a console app

I want to debug a Windows service but it pops an error message saying我想调试一个 Windows 服务,但它弹出一条错误消息说

Cannot start service from the command line or a debugger.无法从命令行或调试器启动服务。 A windows service must be installed using installutil.exe and then started with the Server explorer, windows services Administrative tools or the NET start command.必须使用 installutil.exe 安装 Windows 服务,然后使用服务器资源管理器、Windows 服务管理工具或 NET 启动命令启动。

I don't really have any idea about this error.....我真的不知道这个错误.....

在此处输入图片说明

Before a Windows Service can run, it has to be "installed" first using installutil.在 Windows 服务可以运行之前,必须首先使用 installutil“安装”它。 EG:例如:

C:\installutil -i c:\path\to\project\debug\service.exe

Then you can open up the list of Services to start it.然后你可以打开服务列表来启动它。 EG:例如:

  1. Right click 'My Computer'右键单击“我的电脑”
  2. Click on 'Manage'点击“管理”
  3. Open up 'Services and Applications'打开“服务和应用程序”
  4. Click on 'Services'点击“服务”
  5. Find your service in the list and right-click on it在列表中找到您的服务并右键单击它
  6. Click on 'Start'点击“开始”

Once it has started, you can go into Visual Studio, click on 'Debug', then click on 'Attach to Process'.启动后,您可以进入 Visual Studio,单击“调试”,然后单击“附加到进程”。

Another technique is to add this line to your OnStart() method in the service:另一种技术是将此行添加到服务中的 OnStart() 方法中:

System.Diagnostics.Debugger.Launch();

When you do that, it'll prompt you to pick an instance of Visual Studio to debug the service in.当你这样做时,它会提示你选择一个 Visual Studio 实例来调试服务。

You can alter the assembly's startup mode based on whether you're in DEBUG mode (usually inside Visual Studio but not necessarily) or RELEASE mode (when it runs as a service in production):您可以根据您是处于 DEBUG 模式(通常在 Visual Studio 内,但不一定)还是 RELEASE 模式(当它在生产中作为服务运行时)来更改程序集的启动模式:

Change this:改变这个:

static class Program
{
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService() 
        };
        ServiceBase.Run(ServicesToRun);
    }
}

to that:对此:

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
    }
}

The technique is taken from this article and the credit is for the article's author, Tejas Vaishnav.该技术取自本文,本文作者 Tejas Vaishnav 对此表示感谢。 I copied the code fragments here because SO favors full answers rather than links that might disappear some time.我在这里复制了代码片段,因为 SO 更喜欢完整的答案,而不是可能会消失一段时间的链接。

There is a nuget package made to solve this problem: install-package WindowsService.Gui有一个 nuget 包可以解决这个问题: install-package WindowsService.Gui

跑步者 GUI 的图像

What does the package do?包有什么作用?

It helps by creating a Play/Stop/Pause UI when running with a debugger attached, but also allows the windows service to be installed and run by the Windows Services environment as well.它有助于在连接调试器的情况下运行时创建播放/停止/暂停 UI,但也允许 Windows 服务安装和运行 Windows 服务环境。 All this with one line of code!所有这一切只需一行代码! What is Service Helper Being someone who writes Windows Services a lot, it can be frustrating to deal with the headaches involved in debugging services.什么是 Service Helper 作为一个经常编写 Windows 服务的人,处理调试服务所涉及的头疼问题可能会令人沮丧。 Often it involves tricks, hacks, and partial workarounds to test all of your code.通常它涉及技巧、技巧和部分变通方法来测试您的所有代码。 There is no "just hit F5" experience for Windows Services developers. Windows 服务开发人员没有“按 F5”的体验。

Service Helper solves this by triggering a UI to be shown if a debugger is attached that simulates (as closely as possible) the Windows Services Environment.如果附加了模拟(尽可能接近)Windows 服务环境的调试器,则服务助手通过触发要显示的 UI 来解决此问题。

The github project is here: https://github.com/wolfen351/windows-service-gui github 项目在这里: https : //github.com/wolfen351/windows-service-gui

How to use?如何使用?

The easiest way to get Windows Service Helper in your project is to use the NuGet package ServiceProcess.Helpers on the NuGet official feed.在项目中获取 Windows Service Helper 的最简单方法是使用 NuGet 官方源上的 NuGet 包 ServiceProcess.Helpers。

Simply make a few changes to the typical code in the "Program.cs" for your application:只需对您的应用程序的“Program.cs”中的典型代码进行一些更改:

using System.ServiceProcess;
using ServiceProcess.Helpers; //HERE

namespace DemoService
{
    static class Program
    {
    static void Main()
    {
        ServiceBase[] ServicesToRun;

        ServicesToRun = new ServiceBase[] 
            { 
                new Service1() 
            };

        //ServiceBase.Run(ServicesToRun);
        ServicesToRun.LoadServices(); //AND HERE
    }
    }
}

Disclosure: I'm the maintainer of this project披露:我是这个项目的维护者

Note: The UI is optional注意:UI 是可选的

To prevent this error occurring and allow the service to run outside of the usual service controller you can check the Environment.UserInteractive flag.为了防止发生此错误并允许服务在通常的服务控制器之外运行,您可以检查Environment.UserInteractive标志。 If it is set you can run the service with output to the console instead of letting it run to the ServiceBase code that returns that error.如果设置了它,您可以运行服务并输出到控制台,而不是让它运行到返回该错误的 ServiceBase 代码。

Add this to the start of Program.Main(), before the code that uses ServiceBase to run the service:将此添加到 Program.Main() 的开头,在使用 ServiceBase 运行服务的代码之前:

        if (Environment.UserInteractive)
        {
            var service = new WindowsService();
            service.TestInConsole(args);
            return;
        }

As the OnStart and OnStop methods are protected in your service you need to add another method to that class which you can run from Main() and calls those methods for you, such as:由于 OnStart 和 OnStop 方法在您的服务中protected ,您需要向该类添加另一个方法,您可以从 Main() 运行并为您调用这些方法,例如:

    public void TestInConsole(string[] args)
    {
        Console.WriteLine($"Service starting...");
        this.OnStart(args);
        Console.WriteLine($"Service started. Press any key to stop.");
        Console.ReadKey();
        Console.WriteLine($"Service stopping...");
        this.OnStop();
        Console.WriteLine($"Service stopped. Closing in 5 seconds.");
        System.Threading.Thread.Sleep(5000);
    }

Finally, make sure the output is a console application in the project's properties.最后,确保输出是项目属性中的控制台应用程序。

You can now run the service executable like any other and it will start as a console.您现在可以像运行任何其他服务一样运行该服务可执行文件,它将作为控制台启动。 If you start it from Visual Studio the debugger will attach automatically.如果您从 Visual Studio 启动它,调试器将自动附加。 If you register it and start it as a service it will run properly as a service without any changes.如果您注册它并将其作为服务启动,它将作为服务正常运行,无需任何更改。

The only difference I've found is that when running as a console application the code does not write to the event log, you might want to output anything you would normally log there to the console as well.我发现的唯一区别是,当作为控制台应用程序运行时,代码不会写入事件日志,您可能还想将通常会记录到控制台的任何内容输出到控制台。

This service debugging technique is one of those explained on docs.microsoft.com此服务调试技术是docs.microsoft.com 上解释的技术之一

Please check if you are in "DEBUG" or "RELEASE" mode.请检查您是否处于“调试”或“发布”模式。 I got this error when I was trying to debug the service in "RELEASE" mode.当我尝试在“RELEASE”模式下调试服务时出现此错误。 When I changed that to "DEBUG", everything worked fine.当我将其更改为“调试”时,一切正常。

This is after you have correctly installed the service as suggested by other people above.这是在您按照上述其他人的建议正确安装服务之后。

Another reason can be that the solution configuration is in Release mode in place of Debug mode另一个原因可能是解决方案配置处于发布模式而不是调试模式在此处输入图片说明

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM