pirateofebay
pirateofebay

Reputation: 1090

PowerShell Set Mandatory Property Based on Condition

I need to prompt a user to enter the full path of an executable only if it cannot be found in the system PATH.

I have a parameter block like this:

[CmdletBinding()]
param (
    [Parameter(Mandatory=$true)] [string]$oc_cli,
)

This determines if the executable exists in PATH:

$oc_in_path = [bool] (Get-Command "oc.exe" -ErrorAction Ignore)

I want to set the $oc_cli parameter as mandatory only if $oc_in_path is FALSE.

I have tried

$oc_in_path = [bool] (Get-Command "oc.exe" -ErrorAction Ignore)
function example-function {
    param (
        [Parameter(Mandatory=$oc_in_path)] [string]$oc_cli,
    )
    Write-Host "Do stuff"
}

example-function

which throws error Attribute argument must be a constant or a script block

I have also tried

[CmdletBinding()]
param (
    if (! ( [bool] (Get-Command "oc.exe" -ErrorAction Ignore) )) {
        [Parameter(Mandatory=$true)] [string]$oc_cli
    }
)

How can I set the Mandatory property based on a condition?

Upvotes: 1

Views: 670

Answers (1)

mklement0
mklement0

Reputation: 437588

Try the following, which relies on being able to specify default parameter values via arbitrary commands, using $(...), the subexpression operator:

[CmdletBinding()]
param (
  [Parameter()] # in the absence of property values, this is optional.
  [string] $oc_cli = $(
    if ($cmd = Get-Command -ea Ignore oc.exe) { # oc.exe found in $env:PATH
      $cmd.Path
    } else { # prompt user for the location of oc.exe
      do { 
        $userInput = Read-Host 'Specify the path of executable ''oc.exe''' 
      } until ($cmd = (Get-Command -ea Ignore $userInput))
      $cmd.Path 
    } 
  )
)

"`$oc_cli: [$oc_cli]"

Note:

  • The Mandatory property of the Parameter attribute is not used, as it would - in the absence of an argument being passed - unconditionally prompt for an argument (parameter value).

  • The above would still accept a potentially non-existent $oc_cli argument if passed explicitly; you could use a ValidateScript attribute to prevent hat.

Upvotes: 1

Related Questions