0

I need to restart a service in a powershell script. The problem is that this service is a bit buggy and frequently needs to be shut down several times before it gets into the "stopped" state. Because of that I can't seem to use the Restart-Service cmdlet, instead I need to retry the Stop-Service cmdlet a few times. The same applies to starting the service.

So I figure this is a good place to write a function that will take an action (start or stop) and retry it a few times until it works. The problem is I'm not sure how to pass the action in as a parameter. I could just have the action be a String and then say if action == "start" do starcAction, but that won't be very clean. Is there any way I could pass a cmdlet like Stop-Service in as a parameter?

David says Reinstate Monica
  • 19,209
  • 22
  • 79
  • 122
  • It just sounds like you are asking for switches/booleans. You could have `-Continue` which would initiate a do/until. Else it would just perform action once. Sending a cmdlet seems to needlessly complicate the issue. – Matt Mar 20 '15 at 18:51

2 Answers2

2

For the scenario you described you'd normally do something like this:

$maxTries = 5

switch ($args(0)) {
  'start' {
    Start-Service 'MySvc'
  }

  'stop' {
    $i = 0
    do {
      Stop-Service 'MySvc'
      $i++
    } until ((Get-Service 'MySvc').Status -eq 'Stopped' -or $i -ge $maxTries)
    if ((Get-Service 'MySvc').Status -ne 'Stopped') {
      Write-Error "Cannot stop service."
      exit 1
    }
  }

  default {
    Write-Error "Unknown action: $_"
    exit 1
  }
}

If you really want to avoid string arguments, you could use parameter sets like this:

[CmdletBinding(DefaultParameterSetName='none')]
Param(
  [Parameter(Mandatory=$true,ParameterSetName='start')]
  [Switch][bool]$Start = $false,
  [Parameter(Mandatory=$true,ParameterSetName='stop')]
  [Switch][bool]$Stop = $false
)

$maxTries = 5

switch ($PSCmdlet.ParameterSetName) {
  'start' {
    Start-Service 'MySvc'
  }

  'stop' {
    $i = 0
    do {
      Stop-Service 'MySvc'
      $i++
    } until ((Get-Service 'MySvc').Status -eq 'Stopped' -or $i -ge $maxTries)
    if ((Get-Service 'MySvc').Status -ne 'Stopped') {
      Write-Error "Cannot stop service."
      exit 1
    }
  }

  'none' {
    Write-Error "Usage: $($MyInvocation.MyCommand.Name) {-Start|-Stop}"
    exit 1
  }
}
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
1
Param([Parameter(Mandatory)] [ValidateSet('Start','Stop')] [string] $Action)

This allows the user to press Tab to select the possible values and will automatically reject all invalid input.

Passing in a well defined parameter (doesn't matter if it's a string or not) is actually cleaner than "passing in a commandlet" would be if there was such a thing.