Tarek Saied
Tarek Saied

Reputation: 6626

stop windows service in onStart() method

I want to stop windows service in onStart() method when customer doesn't have a license. I use service.Stop(), but it does not work.

protected override void OnStart(string[] args)
{
    try
    {
        _bridgeServiceEventLog.WriteEntry("new OnStart");
        if (LicenseValidetor.ValidCountAndTypeDevices())
        {
            WsInitializeBridge();
        }
        else
        {
            service = new ServiceController("BridgeService");
            service.Stop();
            _bridgeServiceEventLog.WriteEntry("LicenseValidetor Error");
        }
        _bridgeServiceEventLog.WriteEntry("end Start");
    }
    catch (Exception e)
    {
        _bridgeServiceEventLog.WriteEntry("error In onstart method ");
    }

}

Upvotes: 8

Views: 10083

Answers (4)

HackSlash
HackSlash

Reputation: 5811

The accepted answer explains why what you are doing doesn't work but doesn't offer a good solution.

There are a couple of things your code isn't doing that it should.

  1. Set the .ExitCode to indicate that your service is in an error state.
  2. Throw an exception. Not having a license is exceptional. Throw it.

EXAMPLE:

protected override void OnStart(string[] args)
{
    _bridgeServiceEventLog.WriteEntry("new OnStart");
    try
    {        
        if (LicenseValidetor.ValidCountAndTypeDevices())
        {
            WsInitializeBridge();
        }
        else
        {
            throw new ApplicationException("LicenseValidetor Error");
        }
    }
    catch (Exception e)
    {
        this.ExitCode = e.HResult
        _bridgeServiceEventLog.WriteEntry($"error In onstart method: {e.Message}");
        throw
    }

    _bridgeServiceEventLog.WriteEntry("end Start");
}

Upvotes: 0

Derek
Derek

Reputation: 8630

I have noticed that your not waiting to ensure that the Service has actually stopped or if it is even running in the first instance.

Do this :-

protected override void OnStart(string[] args)
{
    try
    {
        _bridgeServiceEventLog.WriteEntry("new OnStart");
        if (LicenseValidetor.ValidCountAndTypeDevices())
        {
            WsInitializeBridge();
        }
        else
        {
            int time = 10000;

            TimeSpan timeout = TimeSpan.FromMilliseconds(time);

            service.Stop();
            service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);

            _bridgeServiceEventLog.WriteEntry("LicenseValidetor Error");
        }
        _bridgeServiceEventLog.WriteEntry("end Start");
    }
    catch (Exception e)
    {
        _bridgeServiceEventLog.WriteEntry("error In onstart method ");
    }
}

Upvotes: -1

Rolf
Rolf

Reputation: 965

I want to add that "simply not starting any workers" may not work (or perhaps I am being just plain stupid ;) ).

I built a service, with a try/catch(all) around my OnStart code. Because of a missing line in my .config file it crashed with an IOException, before it started any worker thread. The exception skipped over my thread starters. No thread was started by my code. Honestly.

But the service DID NOT STOP. I don't know why. As a desperate measure, I rethrew the exception, that helped.

I am still wondering if the file system watcher threads in Enterprise Library configuration were the problem. EntLib is woven to deeply into my code to remove it as an experiment, so I did not investigate further.

Upvotes: 0

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239814

You cannot stop a service from within the OnStart method of that same service.

The ServiceController.Stop method internally calls ControlService (or it's Ex counterpart). Notice that one of the reasons that this function can fail is:

ERROR_SERVICE_CANNOT_ACCEPT_CTRL The requested control code cannot be sent to the service because the state of the service is SERVICE_STOPPED, SERVICE_START_PENDING, or SERVICE_STOP_PENDING.

Well, guess what - when you're inside your OnStart method, the state of your service is SERVICE_START_PENDING.


The correct way to cope with this situation is to signal any other threads that you may have started to have them exit, and then to exit your OnStart method. The service control manager will notice that the process has exited and revert your service status to SERVICE_STOPPED. It may also notify an interactive user that "The service started and then stopped" or words to that effect.

Upvotes: 8

Related Questions