Windows Service: Persistence of Start Parameters with Automatic Startup Type


3 views

When configuring a Windows Service, the startup parameters passed to the ServiceBase.Run() method play a crucial role in service initialization. A common concern among developers is whether these parameters persist after system reboots when the service startup type is set to "Automatic".

Windows Services configured with Automatic startup type do not preserve command-line parameters across reboots by default. The service control manager (SCM) starts automatic services without any parameters.

// This is how you typically start a service with parameters
static void Main()
{
    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[] 
    { 
        new MyService(args) // Parameters passed here
    };
    ServiceBase.Run(ServicesToRun);
}

To maintain parameters between restarts, consider these approaches:

1. Registry Storage

Store parameters in the Windows Registry during service operation:

// Saving parameters to registry
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"SOFTWARE\MyService");
key.SetValue("StartParams", string.Join("|", args));
key.Close();

// Retrieving during service start
string[] savedParams = ((string)key.GetValue("StartParams", "")).Split('|');

2. Configuration Files

Use application configuration files (app.config/web.config) or custom config files:

<configuration>
  <appSettings>
    <add key="ServiceParam1" value="value1"/>
    <add key="ServiceParam2" value="value2"/>
  </appSettings>
</configuration>

3. Service Recovery Options

Configure recovery actions to restart with parameters:

sc failure "MyService" reset= 0 actions= restart/60000/restart/60000/restart/60000

For robust parameter handling, implement a hybrid approach combining configuration files with registry fallback:

public string[] GetStartupParameters()
{
    // Try config file first
    var configParams = ConfigurationManager.AppSettings["ServiceParams"];
    if (!string.IsNullOrEmpty(configParams))
        return configParams.Split('|');
        
    // Fallback to registry
    using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\MyService"))
    {
        if (key != null)
        {
            var regParams = key.GetValue("StartParams") as string;
            if (!string.IsNullOrEmpty(regParams))
                return regParams.Split('|');
        }
    }
    
    return new string[0]; // Default empty parameters
}
  • Security: Always validate and sanitize stored parameters
  • Encryption: Consider encrypting sensitive parameters in storage
  • Change Detection: Implement mechanisms to detect parameter changes
  • Logging: Maintain logs of parameter changes and service startups

When configuring a Windows Service, developers often need to pass startup parameters to control service behavior. These parameters are typically specified when manually starting the service using the sc start command or the Service Control Manager. However, the persistence of these parameters becomes particularly important when dealing with services configured for automatic startup.

For services with StartupType = Automatic, Windows does not preserve start parameters across system reboots. This is by design - automatic startup initiates the service without any parameters, using only the configuration stored in the registry.


// Example of setting parameters during manual start
sc start MyService param1 param2

The proper way to persist startup parameters is through the service's registry configuration. The parameters should be stored in the ImagePath value under the service's registry key:


HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\MyService

Here are two common methods to implement persistent parameters:

1. Direct Registry Modification


// C# example of modifying registry
using Microsoft.Win32;

RegistryKey key = Registry.LocalMachine.OpenSubKey(
    @"SYSTEM\CurrentControlSet\Services\MyService", true);
    
if (key != null)
{
    string imagePath = key.GetValue("ImagePath").ToString();
    key.SetValue("ImagePath", imagePath + " -param1 -param2");
    key.Close();
}

2. Using SC Command


sc config MyService binPath= "\"C:\Path\To\Service.exe\" -param1 -param2"

For complex scenarios, consider using external configuration files:


// In service code:
var config = ConfigurationManager.AppSettings["ServiceParam"];

When storing parameters in registry or configuration files:

  • Use appropriate registry permissions
  • Consider encrypting sensitive parameters
  • Validate all input parameters

To confirm your parameters are properly set:


sc qc MyService