user1108948
user1108948

Reputation:

Start Windows Service in C#

I want to start a windows service that was just installed.

ServiceBase[] ServicesToRun;
if (bool.Parse(System.Configuration.ConfigurationManager.AppSettings["RunService"]))
{
    ServicesToRun = new ServiceBase[] { new IvrService() };
    ServiceBase.Run(ServicesToRun);
}

The IvrService code is:

partial class IvrService : ServiceBase
{
    public IvrService()
    {
        InitializeComponent();

        Process myProcess;
        myProcess = System.Diagnostics.Process.GetCurrentProcess();

        string pathname = Path.GetDirectoryName(myProcess.MainModule.FileName);

        //eventLog1.WriteEntry(pathname);

        Directory.SetCurrentDirectory(pathname);

    }

    protected override void OnStart(string[] args)
    {
        string sProcessName = Process.GetCurrentProcess().ProcessName;

        if (Environment.UserInteractive)
        {
            if (sProcessName.ToLower() != "services.exe")
            {
                // In an interactive session.
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new IvrInteractive());
                IvrApplication.Start(); // the key function of the service, start it here
                return;
            }
        }
    }

I am not sure how to start the service. Using ServiceController.Start()? But I already have ServiceBase.Run(ServicesToRun); Is it for starting a service?

Code hint is definitely appreciated.

Upvotes: 2

Views: 22622

Answers (3)

    private static bool StartWindowsService(string serviceName)
    {
        bool isStarted = false;
        try
        {
            ServiceController service = new ServiceController(serviceName);
            service.Start();
            var timeout = new TimeSpan(0, 0, 5); // 5seconds
            service.WaitForStatus(ServiceControllerStatus.Running, timeout);
            isStarted = true;
        }
        catch (Exception ex)
        {               
            return isStarted;
        }
        return isStarted;
    }

Upvotes: 0

josh poley
josh poley

Reputation: 7479

To answer the question about starting a service from code, you would want something like this (which would be equivalent to running net start myservice from the command line):

ServiceController sc = new ServiceController();
sc.ServiceName = "myservice";

if (sc.Status == ServiceControllerStatus.Running || 
    sc.Status == ServiceControllerStatus.StartPending)
{
    Console.WriteLine("Service is already running");
}
else
{
    try
    {
        Console.Write("Start pending... ");
        sc.Start();
        sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 10));

        if (sc.Status == ServiceControllerStatus.Running)
        {
            Console.WriteLine("Service started successfully.");
        }
        else
        {
            Console.WriteLine("Service not started.");
            Console.WriteLine("  Current State: {0}", sc.Status.ToString("f"));
        }
    }
    catch (InvalidOperationException)
    {
        Console.WriteLine("Could not start the service.");
    }
}

This will start the service, but keep in mind that it will be a different process than the one that is executing the above code.


Now to answer the question about debugging a service.

  • One option is to attach after the service has been started.
  • The other is to make your service executable be able to run the main code, not as a service but as a normal executable (typically setup via a command line parameter). Then you can F5 into it from your IDE.


EDIT: Adding sample flow of events (based on questions from some of the comments)

  1. OS is asked to start a service. This can be done from the control panel, the command line, APIs (such as the code above), or automatically by the OS (depending on the service's startup settings).
  2. The operating system then creates a new process.
  3. The process then registers the service callbacks (for example ServiceBase.Run in C# or StartServiceCtrlDispatcher in native code). And then starts running its code (which will call your ServiceBase.OnStart() method).
  4. The OS can then request that a service be paused, stopped, etc. At which point it will send a control event to the already running process (from step 2). Which will result in a call to your ServiceBase.OnStop() method.


EDIT: Allowing a service to run as a normal executable or as a command line app: One approach is to configure your app as a console application, then run different code based on a command line switch:

static void Main(string[] args)
{
    if (args.Length == 0)
    {
        // we are running as a service
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] { new MyService() };
        ServiceBase.Run(ServicesToRun);
    }
    else if (args[0].Equals("/debug", StringComparison.OrdinalIgnoreCase))
    {
        // run the code inline without it being a service
        MyService debug = new MyService();
        // use the debug object here
    }

Upvotes: 6

DaveDev
DaveDev

Reputation: 42185

First you need to install the service using InstallUtil, e.g.

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe C:\MyService.exe

You need to start the service from the command line, e.g.

net start ServiceName // whatever the service is called

Then you need to attach to the process with Visual Studio, via Tools > Attach To Process.

Stick the breakpoints in the solution wherever you want it to break and the dev environment should take over.

To start it from the dev environment, put the net start ServiceName command into a batch file, and then in the Project Properties > Build Events "Post Build Event Command Line" you can add the path to the batch file.

*note that looking now, I'm not sure if you need to even use a batch file, you might be able to put the command directly in there. Try and edit this answer with whatever works.

Upvotes: 0

Related Questions