14

I am using InstallUtil to install my service and I just cannot figure out how to specify the startup parameters for it!

Here is my Installer subclass:

[RunInstaller(true)]
public class ServerHostInstaller : Installer
{
  private ServiceInstaller m_serviceInstaller;
  private ServiceProcessInstaller m_serviceProcessInstaller;
  private static string s_usage = "Usage:\ninstallutil /i /username=<user_name> /password=<user_password> NCStub.Server.Host.exe";

  public ServerHostInstaller()
  {
    m_serviceInstaller = new ServiceInstaller();
    m_serviceInstaller.ServiceName = Program.ServiceName;
    m_serviceInstaller.DisplayName = Program.ServiceName;
    m_serviceInstaller.StartType = ServiceStartMode.Automatic;

    m_serviceProcessInstaller = new ServiceProcessInstaller();
    m_serviceProcessInstaller.Account = ServiceAccount.User;

    Installers.Add(m_serviceInstaller);
    Installers.Add(m_serviceProcessInstaller);
  }

  public override void Install(IDictionary stateSaver)
  {
    base.Install(stateSaver);

    string userName = this.Context.Parameters["username"];
    if (userName == null)
    {
      Console.WriteLine(s_usage);
      throw new InstallException("Missing parameter 'username'");
    }

    string userPass = this.Context.Parameters["password"];
    if (userPass == null)
    {
      Console.WriteLine(s_usage);
      throw new InstallException("Missing parameter 'password'");
    }

    m_serviceProcessInstaller.Username = userName;
    m_serviceProcessInstaller.Password = userPass;
  }
}

Can anyone indicate how do I specify the service startup parameters?

Wayne Koorts
  • 10,861
  • 13
  • 46
  • 72
mark
  • 59,016
  • 79
  • 296
  • 580

2 Answers2

15

Found it.

I have rewritten the Install method like so:

public override void Install(IDictionary stateSaver)
{
  string userName = this.Context.Parameters["username"];
  if (userName == null)
  {
    Console.WriteLine(s_usage);
    throw new InstallException("Missing parameter 'username'");
  }

  string userPass = this.Context.Parameters["password"];
  if (userPass == null)
  {
    Console.WriteLine(s_usage);
    throw new InstallException("Missing parameter 'password'");
  }

  m_serviceProcessInstaller.Username = userName;
  m_serviceProcessInstaller.Password = userPass;

  var path = new StringBuilder(Context.Parameters["assemblypath"]);
  if (path[0] != '"')
  {
    path.Insert(0, '"');
    path.Append('"');
  }
  path.Append(" --service");
  Context.Parameters["assemblypath"] = path.ToString();
  base.Install(stateSaver);
}

Although, I give the predefined command line parameters (--service), the code is easily adaptable to pass real command line arguments, just use the same pattern for passing the username and password parameters.

mark
  • 59,016
  • 79
  • 296
  • 580
  • 2
    This approach also works if you attach a handler to the BeforeInstall event of the service installer object rather than overriding the Install method. – Peter Wone Jun 14 '12 at 04:12
  • 2
    Actually no it doesn't. It ought to and I'm fairly sure it used to but I just checked and it doesn't. Stick with the override version. – Peter Wone Jun 14 '12 at 05:39
  • I have the same solution to pass credentials to my installer. The problem is that the log file contains your credentials aswell, which is a big problem in my opinion. Do you have an idea how to disable the writing of "Affected parameters are:" in the logfile? I don't want to disabled the complete logfile! – flayn Sep 13 '12 at 14:47
  • @FlorianGerhardt - Nope. I have moved to Java and Javascript since then, no .NET for the past half a year. Sorry, man. – mark Sep 13 '12 at 17:25
  • 3
    This solution does not work. It produces following command like for service: ""C:\folder\file.exe" --service" – Sergey Jun 17 '15 at 16:09
4

I know this is an old post but thought I'd post my response. I did this in a .net 4 service using the BeforeInstall event.

The ServiceProcessInstaller's BeforeInstall event:

private void serviceProcessInstaller1_BeforeInstall(object sender, InstallEventArgs e)
{
    System.ServiceProcess.ServiceProcessInstaller installer = sender as System.ServiceProcess.ServiceProcessInstaller;

    if (installer != null)
    {
        //Get the existing assembly path parameter
        StringBuilder sbPathWIthParams = new StringBuilder(installer.Context.Parameters["assemblypath"]);

        //Wrap the existing path in quotes if it isn't already
        if (!sbPathWIthParams[0].Equals("\""))
        {
            sbPathWIthParams.Insert(0, "\"");
            sbPathWIthParams.Append("\"");
        }

        //Add desired parameters
        sbPathWIthParams.Append(" test");

        //Set the new path
        installer.Context.Parameters["assemblypath"] = sbPathWIthParams.ToString();
    }
}

The installed service looks as follows: enter image description here

It executes fine, and I can examine the parameters from within the main function of the service.

Jeremy
  • 44,950
  • 68
  • 206
  • 332