DSC Windows Service

Octopus.Script exported 2017-06-20 by dunedinsoftware belongs to ‘Windows’ category.

Starts/stops one or more services asynchronously, and then waits for them to align to the specified state

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Services to align

Services

A comma delimited list of services or wildcards (eg. “Sky”) to align

Services to ignore

ServicesToIgnore

A comma delimited list of services or wildcards (eg. “Sky”) to ignore

Desired state

DesiredState

The desired state of the service/s. Specify either “Started” or “Stopped”

Timeout in seconds

TimeoutSeconds = 300

The number of seconds to wait for the service/s to align before timing out and throwing an exception

Script body

Steps based on this template will execute the following PowerShell script.


    $ServicesToManage = $OctopusParameters['Services']
    $ServicesToIgnore = $OctopusParameters['ServicesToIgnore']
    $TimeoutSeconds = $OctopusParameters['TimeoutSeconds']
    $DesiredState = $OctopusParameters['DesiredState']

    # Gather information about the list of services
    $services_status = @{}

    # For each "service to manage" or wildcard specified ...
    $ServicesToManage -split "," |% `
    {
        $service = $_
    
        # ... retrieve all the services that match that name or wildcard ...
        $service_states = Get-Service |? { $_.Name -match $service }
    
        # ... and add them into an array; we use a key/value array so that services only get added to the array once, even if they are
        # matched by multiple wildcard specifications
        $service_states |% { $services_status[$_.Name] = $_.Status }
    }
    
    # For each "service to ignore" or wildcard specified ...
    $ServicesToIgnore -split "," |% `
    {
        $service = $_
        
        # Copy the keys within services_status, since we will need to change services_status as we enumerate them
        $keys = @()
        $services_status.Keys |% { $keys += $_ }
        
        $keys |% `
        {
           $key = $_
 
           if ($key -match $service -and $service -match "[a-z]+")
           {
                $services_status.Remove($_)
           }
        }
    }

    Write-Host "Matched the following set of services, along with their current status:"
    $services_status

    # Now act as required to bring the services to the desired configuration state
    [DateTime]$startTime = [DateTime]::Now
    
    # State to pass to sc
    $state_type = if ($DesiredState -match "Stopped") { "stop" } else { "start" }

	$unaligned_services = ($services_status.Keys |? { $services_status[$_] -notmatch $DesiredState })
	# Attempt to align the remaining services
	$unaligned_services |% `
	{ 
		Write-Host "Attempting to $state_type service: $_"
		Start-Process -FilePath "cmd" -ArgumentList "/c sc.exe $state_type `"$_`""
	}	
   
   while ($startTime.AddSeconds($TimeoutSeconds) -gt [DateTime]::Now)
    {
		# Attempt to align the remaining services
		$unaligned_services |% `
		{ 
			Write-Host "Attempting to $state_type service: $_"
			$services_status[$_] = Get-Service $_ | Select-Object -Property "Status"
		}	
		$unaligned_services = ($services_status.Keys |? { $services_status[$_] -notmatch $DesiredState })
		Write-Host "$([DateTime]::Now): $($unaligned_services.Count) services of $($services_status.Count) not yet at status: $DesiredState"
		
        if ($unaligned_services.Count -eq 0)
        {
            Write-Host "All services now at desired state; exiting"
            exit 0
        }

          
        # Pause for a second
        [System.Threading.Thread]::Sleep(1000)
    }

    throw "Error: not all services reached the desired state within the specified timeframe: $unaligned_services"



Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "1cdf63ce-50c8-45a8-cce2-f6ca2d6d617b",
  "Name": "DSC Windows Service",
  "Description": "Starts/stops one or more services asynchronously, and then waits for them to align to the specified state",
  "Version": 15,
  "ExportedAt": "2017-06-20T14:35:09.389Z",
  "ActionType": "Octopus.Script",
  "Author": "dunedinsoftware",
  "Parameters": [
    {
      "Name": "Services",
      "Label": "Services to align",
      "HelpText": "A comma delimited list of services or wildcards (eg. \"Sky\") to align",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "ServicesToIgnore",
      "Label": "Services to ignore",
      "HelpText": "A comma delimited list of services or wildcards (eg. \"Sky\") to ignore",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "DesiredState",
      "Label": "Desired state",
      "HelpText": "The desired state of the service/s. Specify either \"Started\" or \"Stopped\"",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "Running|Started\nStopped|Stopped"
      }
    },
    {
      "Name": "TimeoutSeconds",
      "Label": "Timeout in seconds",
      "HelpText": "The number of seconds to wait for the service/s to align before timing out and throwing an exception",
      "DefaultValue": "300",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptBody": "\n    $ServicesToManage = $OctopusParameters['Services']\n    $ServicesToIgnore = $OctopusParameters['ServicesToIgnore']\n    $TimeoutSeconds = $OctopusParameters['TimeoutSeconds']\n    $DesiredState = $OctopusParameters['DesiredState']\n\n    # Gather information about the list of services\n    $services_status = @{}\n\n    # For each \"service to manage\" or wildcard specified ...\n    $ServicesToManage -split \",\" |% `\n    {\n        $service = $_\n    \n        # ... retrieve all the services that match that name or wildcard ...\n        $service_states = Get-Service |? { $_.Name -match $service }\n    \n        # ... and add them into an array; we use a key/value array so that services only get added to the array once, even if they are\n        # matched by multiple wildcard specifications\n        $service_states |% { $services_status[$_.Name] = $_.Status }\n    }\n    \n    # For each \"service to ignore\" or wildcard specified ...\n    $ServicesToIgnore -split \",\" |% `\n    {\n        $service = $_\n        \n        # Copy the keys within services_status, since we will need to change services_status as we enumerate them\n        $keys = @()\n        $services_status.Keys |% { $keys += $_ }\n        \n        $keys |% `\n        {\n           $key = $_\n \n           if ($key -match $service -and $service -match \"[a-z]+\")\n           {\n                $services_status.Remove($_)\n           }\n        }\n    }\n\n    Write-Host \"Matched the following set of services, along with their current status:\"\n    $services_status\n\n    # Now act as required to bring the services to the desired configuration state\n    [DateTime]$startTime = [DateTime]::Now\n    \n    # State to pass to sc\n    $state_type = if ($DesiredState -match \"Stopped\") { \"stop\" } else { \"start\" }\n\n\t$unaligned_services = ($services_status.Keys |? { $services_status[$_] -notmatch $DesiredState })\n\t# Attempt to align the remaining services\n\t$unaligned_services |% `\n\t{ \n\t\tWrite-Host \"Attempting to $state_type service: $_\"\n\t\tStart-Process -FilePath \"cmd\" -ArgumentList \"/c sc.exe $state_type `\"$_`\"\"\n\t}\t\n   \n   while ($startTime.AddSeconds($TimeoutSeconds) -gt [DateTime]::Now)\n    {\n\t\t# Attempt to align the remaining services\n\t\t$unaligned_services |% `\n\t\t{ \n\t\t\tWrite-Host \"Attempting to $state_type service: $_\"\n\t\t\t$services_status[$_] = Get-Service $_ | Select-Object -Property \"Status\"\n\t\t}\t\n\t\t$unaligned_services = ($services_status.Keys |? { $services_status[$_] -notmatch $DesiredState })\n\t\tWrite-Host \"$([DateTime]::Now): $($unaligned_services.Count) services of $($services_status.Count) not yet at status: $DesiredState\"\n\t\t\n        if ($unaligned_services.Count -eq 0)\n        {\n            Write-Host \"All services now at desired state; exiting\"\n            exit 0\n        }\n\n          \n        # Pause for a second\n        [System.Threading.Thread]::Sleep(1000)\n    }\n\n    throw \"Error: not all services reached the desired state within the specified timeframe: $unaligned_services\"\n\n\n"
  },
  "Category": "Windows",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/dsc-windows-service.json",
  "Website": "/step-templates/1cdf63ce-50c8-45a8-cce2-f6ca2d6d617b",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////Da3qSsLvhtb0wur6O7zuWcfxldv2aMzyK7ftpOD3s+X48Pr+0fD7d9HzHLLr4fX8xD/OcwAAAaNJREFUeNrs3cFygjAUQFECWott1f//2sJoW6kIKEzNs+euXOmcmSSGDa8oJEmSJEmSJGmsj1W1K9cpsGD1Vr2WdToVEPC+2lYvZfpVrEW0qZpF1F+MRdRugzoNlvkiarfBPk0pT8GhWUSX2yASpDlLr2+DEJBmEY1ug6whx7N0n2b30G1QlmmxHsRYp6X76yvF9vg5RYQczq8UVURI35UiFmTgShED0p6lI1eKzCHTrxS5Qk6PZ9PLDtJ9PIsJmXWlyAky6/dAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQMJCyjltF/iO3gpJUpD8s4OAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8T8itwwKyhbTdMr4ha8hXUwZqhICcOgyNOIkE+V5wo4MSgr1u/fp7poO+AL8K/gL8yw0UeyRB34m9iQ/pVD8L5JYTO3NI58R+AsiEEzsW5OfE3sUe/zRwYkeGnG2g2CPS7rhjF4GKP0ZwyoldxK37kFqEL/7wU0mSJEmSJOmJ+xRgAHxZTCXGdZkfAAAAAElFTkSuQmCC",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Tuesday, June 20, 2017