InstallUtil, Windows Services & ProjectInstallers with App.Config Settings

Config FunWe had a situation in work where we needed to make service installation a more configurable process.

So a very simple example, In order to install a .NET Windows Service we need to provide it with a username & password that the services will run as. We can either provide that information at installation time, or through the following properties in the ProjectInstaller.cs file for your service.

However in an environment where multiple developers are working on a service, particularly a service that requires elevated privileges and needs to run as a specific account, this can be a royal pain.

private void InitializeComponent()
{
    this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
    this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();

    this.serviceProcessInstaller1.Username = "MYPC\JohnSmith";
    this.serviceProcessInstaller1.Password = "abcd1234";

    this.serviceInstaller1.ServiceName = "My Service";
    this.serviceInstaller1.Description = "My Description";

    this.Installers.AddRange(new System.Configuration.Install.Installer[] {
	this.serviceProcessInstaller1,	this.serviceInstaller1});
}

Option 1. Type in the credentials every time the service is Installed/Started... a not-so-ideal manual process when constantly re-starting a service to debug. It's also a pain for an automated xcopy releases where there is one big batch job which will stop, uninstall, reinstall & re-start every service in the deployment.

Option 2. Leave the account credentials hard-coded in. This isn't ideal either. With Local Dev Environments, Shared Development Environments and Staging & Production platforms, it's too easy to leave the wrong credentials hardcoded into the ProjectInstaller, or worse, introduce a small typo/bug when the values are changed/recompiled between environment releases.

Wouldn't it be better if this could be configurable ?

Unfortunately, we need to do a little gymnastics in order to gain access to the .config file of the service at installation time when using InstallUtil.exe. The App.config Configuration File which the ConfigurationManager is using during the installation process is actually InstallUtil.exe.config... not what we want. Instead, we can manually load the associated configuration file for the assembly which contains the Project Installer, and retrieve our settings from that.

private static string GetConfigurationValue(string key)
{
    var service = Assembly.GetAssembly(typeof(ProjectInstaller));
    Configuration config = ConfigurationManager.OpenExeConfiguration(service.Location);
    if (config.AppSettings.Settings[key] == null)
    {
        throw new IndexOutOfRangeException("Settings collection does not contain the requested key:" + key);
    }

    return config.AppSettings.Settings[key].Value;
}

We can now add our installation information to the configuration file which is template controlled under our release process.

private void InitializeComponent()
{
    this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
    this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();

    this.serviceProcessInstaller1.Password = GetConfigurationValue("ServicePassword");
    this.serviceProcessInstaller1.Username = GetConfigurationValue("ServiceUserName");

    this.serviceInstaller1.ServiceName = "Service Name";
    this.serviceInstaller1.Description = "Service Description - " + GetConfigurationValue("ServiceLabel"); 
    //E.g. ServiceLabel = "LOCAL EOINC";

    this.Installers.AddRange(new System.Configuration.Install.Installer[] {
	this.serviceProcessInstaller1,
	this.serviceInstaller1});
}

The usual caveats about config file encryptions and protecting your passwords apply.

Eoin Campbell

Eoin Campbell

Eoin Campbell
Dad, Husband, Coder, Architect, Nerd, Runner, Photographer, Gamer. I work primarily on the Microsoft .NET & Azure Stack for ChannelSight

CPU Spikes in Azure App Services

Working with Azure App Services and plans which have different CPU utilization profiles Continue reading

Building BuyIrish.com

Published on November 05, 2020

Data Partitioning Strategy in Cosmos DB

Published on June 05, 2018