Again, we want to have a way to setup our environments while easily maintaining the mechanism. Separating the configuration settings and scripts is very important since eventually we would like to have our end-users can maintain their data without worrying the code/scripts and vise versa.

First is the template of configuration files.

<Server id="MyServer">
  <Services>
    <Service id="MyService1">
      <DisplayName>My Service 1</DisplayName>
      <BinaryPath>D:MyServiceBin\MyService1.exe</BinaryPath>
      <LogonAsAccount>MyServiceAccount1</LogonAsAccount>
      <LogonAsPassword>MyPassword1</LogonAsPassword>
      <StartType>delayed-auto</StartType>
    </Service>
    <Service id="MyService2">
      <DisplayName>My Service 2</DisplayName>
      <BinaryPath>D:MyServiceBin\MyService2.exe</BinaryPath>
      <LogonAsAccount>MyServiceAccount2</LogonAsAccount>
      <LogonAsPassword>MyPassword2</LogonAsPassword>
      <StartType>delayed-auto</StartType>
    </Service>
  </Services>
</Server>

Second, let’s make a PS script to do the work

function SetupAService ($serviceName, $displayName, $binaryPath, $serviceActName, $serviceActPasswd, $startType) 
{ 
	# verify if the service already exists, and if yes remove it first
	if (Get-Service $serviceName -ErrorAction SilentlyContinue)
	{
		# using WMI to remove Windows service because PowerShell does not have CmdLet for this
		$serviceToRemove = Get-WmiObject -Class Win32_Service -Filter "name='$serviceName'"
		$serviceToRemove.delete()
		"service removed: $serviceName"
	}
	else
	{
		# just do nothing
		"service does not exists"
	}

	"installing service"
	# creating credentials which can be used to run my windows service

	$secpasswd = ConvertTo-SecureString $serviceActPasswd -AsPlainText -Force
	$mycreds = New-Object System.Management.Automation.PSCredential ($serviceActName, $secpasswd)

	# creating widnows service using all provided parameters
	New-Service -name $serviceName -binaryPathName $binaryPath -displayName $displayName -startupType Automatic -credential $mycreds
	if ([string]::Compare($startType,"delayed-auto", $True) -eq 0)
	{
        $scCommand = "sc.exe config '$serviceName' start= delayed-auto"
        write-host "scCommand: $scCommand"
        Invoke-Expression -Command $scCommand -ErrorAction Stop
	}

	"Installation Completed"
}

Then of course, let’s have another PS script to loop through the config file and setup them one by one.

# Source in SetupAService.ps1
. ".\SetupAService.ps1"

### Read the config XML
# [xml]$thisServer = Get-Content $scriptRoot\Config\UAT\MyServer.xml
$configFile = $args[0]
[xml]$thisServer = Get-Content $configFile

### Create a service for each element in the xml file (under services)
$thisServer.Server.Services.Service| foreach {SetupAService $_.id $_.DisplayName $_.BinaryPath $_.LogonAsAccount $_.LogonAsPassword $_.StartType}

OK, from now on, just try to keep the config files up-to-date. If you really committed to this, you can use it to refresh your existing environments as well. next time, I will try to have another script to do the audit.

Advertisements