简体   繁体   中英

Can command line arguments be passed to Service class when using InstallUtil?

Problem

I am trying to pass arguments from the command line to my service class that inherits ServiceBase before the service installation. I found a way to accept parameters when using InstallUtil to run my service installer. However, the the main function running ServiceBase.Run(new Service());triggers before those parameters can be accessed. Therefore, I don't know how to pass command line parameters into my Service() class before it is run.

I am using ConfigStream as a static class to read and store parameters from a text config file. My goal is to import the settings from the config file and apply them to my Service class before the installer is run. I'd like to be able to point to the location of that config file from an input in the command line.

Attempted Solutions

I've tried applying the parameters to the ConfigStream class within the OnBeforeInstall function of the Installer, but that still runs after the main function, so it doesn't apply the settings to my Service class.

I also tried following a tutorial from microsoft, but also had no luck. The parameters were never passed to Main. Tutorial: Create Windows Service - Add Optional Params

Main Class


    public static class MainClass
    {
        ///Function: Main
        ///File: ServiceWrapperV2.cs
        ///Author: Luke Maple
        ///Purpose: Main function of program, start up the service portion of program.
        static void Main(String[] args)
        {
            // Test if input arguments were supplied
            Console.WriteLine("Args: ");
            Console.WriteLine(args);
            if (args.Length > 0)
            {
                // set config location if provided
                // otherwise assume in working directory
                ConfigStream.setConfigstream(args[0]);
            }
            // run service
            ServiceBase.Run(new Service());
        }
    }

Installer Attempt 1


    [RunInstaller(true)]
    public class ServiceWrapperInstaller : Installer
    {
        private ServiceProcessInstaller processInstaller;
        private ServiceInstaller serviceInstaller;

        public ServiceWrapperInstaller()
        {
            //inilizing installer objects 
            processInstaller = new ServiceProcessInstaller();
            serviceInstaller = new ServiceInstaller();

            //Service will use the windows local system acount. Service will be run as admin
            processInstaller.Account = ServiceAccount.LocalSystem;

            //sets service start mode to automatic. service will auto boot on restarts
            serviceInstaller.StartType = ServiceStartMode.Automatic;

            // set service parameters
            // Console.WriteLine(ConfigStream.getSetting("Service Name"));
            serviceInstaller.ServiceName = ConfigStream.getSetting("Service Name");
            // Console.WriteLine("\nService Name: " + serviceInstaller.ServiceName + "\n");
            serviceInstaller.Description = ConfigStream.getSetting("Service Description");

            //passing object to be installed
            Installers.Add(serviceInstaller);
            Installers.Add(processInstaller);
        }

        private void _setConfigLocation()
        {
            if (Context.Parameters.ContainsKey("config"))
            {
                ConfigStream.setConfigstream(Context.Parameters["config"]);
            }
        }

        protected override void OnBeforeInstall(IDictionary savedState)
        {
            _setConfigLocation();
            base.OnBeforeInstall(savedState);
        }
    }

Installer Attempt 2


    [RunInstaller(true)]
    public class ServiceWrapperInstaller : Installer
    {
        private ServiceProcessInstaller processInstaller;
        private ServiceInstaller serviceInstaller;

        public ServiceWrapperInstaller()
        {
            //inilizing installer objects 
            processInstaller = new ServiceProcessInstaller();
            serviceInstaller = new ServiceInstaller();

            //Service will use the windows local system acount. Service will be run as admin
            processInstaller.Account = ServiceAccount.LocalSystem;

            //sets service start mode to automatic. service will auto boot on restarts
            serviceInstaller.StartType = ServiceStartMode.Automatic;

            // set service parameters
            // Console.WriteLine(ConfigStream.getSetting("Service Name"));
            serviceInstaller.ServiceName = ConfigStream.getSetting("Service Name");
            // Console.WriteLine("\nService Name: " + serviceInstaller.ServiceName + "\n");
            serviceInstaller.Description = ConfigStream.getSetting("Service Description");

            //passing object to be installed
            Installers.Add(serviceInstaller);
            Installers.Add(processInstaller);
        }

        protected override void OnBeforeInstall(IDictionary savedState)
        {
            string parameter = "Config";
            Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\"";
            base.OnBeforeInstall(savedState);
        }
    }

ConfigStream


    public static class ConfigStream
    {
        // set class properties of ConfigStream
        public static string config { get; private set; } = GlobalVariables.cwd + "\\" + GlobalVariables.configFileName;

        // constructor with config as an argument
        public static void setConfigstream(string config_location)
        {
            string config = config_location;
        }

        ///Function: (static) getSetting
        ///Purpose: get requested value form formatted config file
        public static string getSetting(string setting)
        {
        ...
        }
    ...
    }

You can try something like this:

[RunInstaller(true)]
public partial class ServiceWrapperInstaller  : Installer
{
    private const string nameKey = "name";
    private const string displayNameKey = "displayname";
    private const string descriptionKey = "description";

    protected override void OnBeforeInstall(IDictionary savedState)
    {
        // Set installer parameters
        SetParameters();

        base.OnBeforeInstall(savedState);
    }

    private void SetParameters()
    {
        // Set service name
        _serviceInstaller.ServiceName = this.Context.Parameters[nameKey];

        // Set the display name (if provided)
        if (Context.Parameters.ContainsKey(displayNameKey))
        {
            _serviceInstaller.DisplayName = this.Context.Parameters[displayNameKey];
        }

        // Set the description (if provided)
        if (Context.Parameters.ContainsKey(descriptionKey))
        {
            _serviceInstaller.Description = this.Context.Parameters[descriptionKey];
        }

        _serviceInstaller.StartType = ServiceStartMode.Automatic;
        _serviceInstaller.DelayedAutoStart = true;
    }
}

You can use it like this:

InstallUtil /u /name= /displayname=<\\"Display Name\\"> /description=<\\"Description of Service\\"

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