views:

3339

answers:

5

Hi all,

I am currently developing a Windows Service with a .Net 3.5 target.

I am having a number of issues with this:

  1. Although I have a setup project in the solution it doesent install the service (platform is vista) even tho the installer completes successfully. I have to manually install the service using the InstallUtil.exe which is in the .Net 2.0 folder and not the 3.5 folder.

  2. I can not access the app.config using the ConfigrationManager object. I suspect this is because the running service is not run from it's install directory. Does anyone know a way for me to access this at runtime safely?

Any advice and experience on this subject would be much appreciated.

James

+2  A: 

Installing the service requires creating a custom action in your setup project, otherwise it doesn't get registered.

Otávio Décio
+2  A: 

Hi James,

I recently did this myself, and here is code that will allow you to pass "/install" or "/uninstall" as a command line option to install your service. You can change this to automatically install if you'd like. It also accesses the app.config fine (my original service does this in its main loop). As you can see, I am setting it to run as a specific user, but you can set spi.Account = ServiceAccount.LocalSystem; and omit the name and password. Hope this helps:

namespace MyService
{   
    public class ServiceMonitor : ServiceBase
    {
        private System.ComponentModel.Container _components = null;
        private static string _service_name = "MyServiceName";

        public ServiceMonitor()
        {
            InitializeComponent();
        }

        private void InitializeComponent()
        {
            this.CanHandlePowerEvent = true;
            this.CanPauseAndContinue = true;
            this.CanShutdown = true;
            this.CanStop = true;
            this.ServiceName = _service_name;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && _components != null)
            {
                _components.Dispose();
            }
            base.Dispose(disposing);
        }

        static void Main(string[] args)
        {
            string opt = null;            

            if (args.Length >= 1)
            {
                opt = args[0].ToLower();
            }


            if (opt == "/install" || opt == "/uninstall")
            {
                TransactedInstaller ti = new TransactedInstaller();
                MonitorInstaller mi = new MonitorInstaller(_service_name);

                ti.Installers.Add(mi);

                string path = String.Format("/assemblypath={0}", Assembly.GetExecutingAssembly().Location);
                string[] cmdline = { path };

                InstallContext ctx = new InstallContext("", cmdline);

                ti.Context = ctx;

                if (opt == "/install")
                {
                    Console.WriteLine("Installing");
                    ti.Install(new Hashtable());
                }
                else if (opt == "/uninstall")
                {
                    Console.WriteLine("Uninstalling");
                    try
                    {
                        ti.Uninstall(null);
                    }
                    catch (InstallException ie)
                    {
                        Console.WriteLine(ie.ToString());
                    }
                }
            }
            else
            {
                ServiceBase[] services;
                services = new ServiceBase[] { new ServiceMonitor() };
                ServiceBase.Run(services);
            }
        }

        protected override void OnStart(string[] args)
        {
            //
            // TODO: spawn a new thread or timer to perform actions in the background.
            //
            base.OnStart(args);
        }

        protected override void OnStop()
        {
            //
            // TODO: stop your thread or timer
            //
            base.OnStop();
        }
    }

    [RunInstaller(true)]
    public class MonitorInstaller : Installer
    {
        public MonitorInstaller()
            : this("MyServiceName")
        {
        }

        public MonitorInstaller(string service_name)
        {
            ServiceProcessInstaller spi = new ServiceProcessInstaller();

            spi.Account = ServiceAccount.User;
            spi.Password = ConfigurationManager.AppSettings["Password"];
            spi.Username = ConfigurationManager.AppSettings["Username"];

            ServiceInstaller si = new ServiceInstaller();

            si.ServiceName = service_name;
            si.StartType = ServiceStartMode.Automatic;
            si.Description = "MyServiceName";
            si.DisplayName = "MyServiceName";

            this.Installers.Add(spi);
            this.Installers.Add(si);
        }
    }
}
esac
+1  A: 

As others have said you have to create a setup project to do the installation. I've also written batch files to do it without the setup.

For help creating a setup project, I've found the following links to be helpful.

How to create a setup project for a Windows Service application in Visual C#

Windows Services in C#: Part 2: Adding an Installer for Your Windows Service

How to: Add Installers to Your Service Application

Kinze
A: 

Thanks for all your help everyone!