Skip to content

PowerShell Task Authoring

Setup and Prelude

  • Include {{template "prelude.ps1.tmpl" .}} at the start
  • Template entry MUST have Meta: OS: "windows"
  • Template Name should end in .ps1
  • prelude.ps1.tmpl provides:
    • $ErrorActionPreference = "Stop" — halt on errors
    • C:\curtin path added to $env:Path
    • $env:RS_MC_ROLE, $env:RS_MC_TYPE, $env:RS_MC_NAME set
    • Debug support: Set-PSDebug -Trace 1 when rs-debug-enable is true

Error Handling

  • prelude sets $ErrorActionPreference = "Stop" — cmdlet errors are terminating
  • Use try/catch for graceful error handling:

    PowerShell
    try {
        # risky operation
        Set-ItemProperty -Path "HKLM:\Software\MyApp" -Name "Config" -Value $val
    } catch {
        Write-Host "FATAL: Failed to set registry: $_"
        exit 1
    }
    
  • Always use explicit exit 0 for success, exit 1 for failure

Common Patterns

  • Run drpcli: $result = & drpcli machines show $env:RS_UUID | ConvertFrom-Json
  • Registry: Set-ItemProperty, Get-ItemProperty, New-ItemProperty
  • Services: Get-Service, Start-Service, Set-Service -StartupType Automatic
  • File operations: Set-Content, Get-Content, Test-Path
  • Conditional param:

    PowerShell
    {{ if .ParamExists "my-param" }}
    $myVal = "{{ .Param "my-param" }}"
    {{ else }}
    $myVal = "default"
    {{ end }}
    

Complete Example

YAML
---
Name: "example-windows-config"
Description: "Configure a Windows service via registry"
Documentation: |
  Sets registry values for the example Windows service based on DRP parameters.
RequiredParams:
  - example/registry-value
OptionalParams:
  - rs-debug-enable
Meta:
  icon: "windows"
  color: "blue"
  title: "Example Content"
  feature-flags: "sane-exit-codes"
Templates:
  - Name: "example-windows-config.ps1"
    Meta:
      OS: "windows"
    Contents: |
      {{template "prelude.ps1.tmpl" .}}

      $regValue = "{{ .Param "example/registry-value" }}"
      $regPath = "HKLM:\Software\ExampleSvc"

      # Idempotency check
      if (Test-Path $regPath) {
          $current = (Get-ItemProperty -Path $regPath).Config
          if ($current -eq $regValue) {
              Write-Host "Registry already configured correctly"
              exit 0
          }
      }

      try {
          if (-not (Test-Path $regPath)) {
              New-Item -Path $regPath -Force | Out-Null
          }
          Set-ItemProperty -Path $regPath -Name "Config" -Value $regValue
          Write-Host "Registry configured: $regPath\Config = $regValue"
      } catch {
          Write-Host "FATAL: Registry update failed: $_"
          exit 1
      }

      exit 0