D-W
D-W

Reputation: 5341

Debugging a Windows Service - Prevent Cannot Start Service

Trying to deubg a windows service (removed the need to install, code, install, code, etc..), thought I found the solution

class Program
{
    static void Main(string[]args) 
    {
        ClientService service = new ClientService();

        if (args.Length > 0) 
        {
            Task.Factory.StartNew(service.Main, TaskCreationOptions.LongRunning);

            Console.WriteLine("running...");
            Console.ReadLine();

        }
        else 
        {
#if (!DEBUG)
            ServiceBase[]ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new MyService()
            };
            ServiceBase.Run(ServicesToRun);
# else
            ServiceBase.Run(service);
        }
# endif
    }
}

However I'm still getting the error:

Cannot start service from the command line or debugger. A windows Service must first be installed(using installutil.exe) and then started with the ServerExplorer, Windows Services Administrative tool or the NET START command.

enter image description here

Any Ideas what I need to change to avoid the prompt?

Upvotes: 2

Views: 12899

Answers (4)

CodeCaster
CodeCaster

Reputation: 151588

You have copied the code from Running Windows Service Application without installing it, but it was broken by design and you altered it incorrectly.

The thought behind it, is that you have a ServiceBase-inheriting class containing a public method that performs the actual service logic:

public class MyService : ServiceBase
{
    public void DoTheServiceLogic()
    {
        // Does its thing
    }

    public override void OnStart(...)
    {
        DoTheServiceLogic();
    }
}

Then in your application, you can start it like this:

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

        ServiceBase.Run(ServicesToRun);
    }
}

This provides an executable application that can be installed as a Windows Service.

But you don't want to have to install your service and then attach Visual Studio to debug it; that's a horribly inefficient workflow.

So what the code you found attempts to do, as many approaches found online do, is to start the application with a certain command line flag, say /debug, which then calls the public method on the service logic - without actually running it as a Windows Service.

That can be implemented like this:

class Program
{
    static void Main(string[] args)
    {

        if (args.Length == 1 && args[0] == "/debug")
        {
            // Run as a Console Application
            new MyService().DoTheServiceLogic();
        }
        else
        {
            // Run as a Windows Service
            ServiceBase[] ServicesToRun = new ServiceBase[] 
            { 
                new MyService() 
            };

            ServiceBase.Run(ServicesToRun);
        }
    }
}

Now you can instruct Visual Studio to pass the /debug flag when debugging your application, as explained in MSDN: How to: Set Start Options for Application Debugging.

That's slightly better, but still a bad approach. You should extract the service logic altogether, and write unit tests to be able to test your logic without having to run it inside an application, let alone a Windows Service.

Upvotes: 8

Christopher Lake
Christopher Lake

Reputation: 378

In Program.cs

class Program
{
    static void Main(string[] args)
    {
        #if DEBUG
        new ClientService().Start();
        Thread.Sleep(Timeout.Infinite); //Ensure your service keeps running             
        #else
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService() 
        };
        ServiceBase.Run(ServicesToRun);
        #endif
    }
}

In ClientService.cs

public void Start()
{
    OnStart(null);
}

Upvotes: 0

Shlomi Haver
Shlomi Haver

Reputation: 974

Here is what you can do:

Create a partial class with the same name as tour service:

 public partial class AlertEngineService
    {
        public void Run(string[] args)
        {

            OnStart(args);
            Console.WriteLine("Press any key to stop program alert engine service");
            Console.Read();
            OnStop();
        }
    }
}

and call this command on debug:

var servicesToRun = new ClientService ();
servicesToRun.Run(args);

you can also change the service configuration to run as console (in the properties section).

Hope it helps

Upvotes: 2

mrogal.ski
mrogal.ski

Reputation: 5920

Start with changing your code a bit :

static void Main(string[] args)
{
#if DEBUG // If you are currently in debug mode
    ClientService service = new ClientService (); // create your service's instance
    service.Start(args); // start this service
    Console.ReadLine(); // wait for user input ( enter key )
#else // else you're in release mode
    ServiceBase[] ServicesToRun; // start service normally
    ServicesToRun = new ServiceBase[] 
    { 
        new MyService() 
    };
    ServiceBase.Run(ServicesToRun);
#endif
}

In your service add this method :

public void Start(string[] args)
{
    OnStart(args);
}

Now all you need to change is in properties change application type from Windows Application to Console Application.

Upvotes: 0

Related Questions