简体   繁体   中英

Run a Windows Service as a console app

I want to debug a Windows service but it pops an error message saying

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.

I don't really have any idea about this error.....

在此处输入图片说明

Before a Windows Service can run, it has to be "installed" first using 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'.

Another technique is to add this line to your OnStart() method in the service:

System.Diagnostics.Debugger.Launch();

When you do that, it'll prompt you to pick an instance of Visual Studio to debug the service in.

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):

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. I copied the code fragments here because SO favors full answers rather than links that might disappear some time.

There is a nuget package made to solve this problem: 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. 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. 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.

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.

The github project is here: 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.

Simply make a few changes to the typical code in the "Program.cs" for your application:

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

To prevent this error occurring and allow the service to run outside of the usual service controller you can check the Environment.UserInteractive flag. 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.

Add this to the start of Program.Main(), before the code that uses ServiceBase to run the service:

        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:

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

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. 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在此处输入图片说明

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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