3

I have a PowerShell function that takes an optional parameter, validated using a ValidateSetAttribute, and based on that value it adds another dynamic parameter. However, in strict mode, when trying to access the parameter inside of the DynamicParam block, and I didn’t explicitely set said parameter, then I get an error that the variable was not defined.

Param(
    [Parameter()]
    [ValidateSet('A', 'B')]
    [string] $Target = 'A'
)
DynamicParam {
    if ($Target -eq 'B') { # <- Here it fails
        # Add new parameter here...
    }
}
end {
    Write-Host $Target
}

The script works when called with A or B as the first parameter, but fails when the parameter is omitted. Interestingly, if I remove either the ParameterAttribute or the ValidateSetAttribute from the parameter definition it works.

My current workaround is to access the variable using $PSBoundParameters and check if the parameter was set, like this:

if ($PSBoundParameters.ContainsKey('Target') -and $PSBoundParameters.Target -eq 'B') {
    # Add new parameter here...
}

While this works fine, it has one downside if I want to check for the value A instead: As A is the parameter’s default value it won’t be added to $PSBoundParameters when the parameter is omitted and the default value is applied. So I need to modify my check to explicitely check that:

if (-not $PSBoundParameters.ContainsKey('Target') -or $PSBoundParameters.Target -eq 'A')) {
    # Add new parameter here...
}

I don’t really like this solution as it will unnecessarily tie the dynamic parameter addition with the default values. Ideally, I would want to be able to change the default value without having to touch anything else. Is there any way to access the actual parameter value from within the DynamicParam block? Or is there at least a possibility to access the parameter definition and access the default value?

poke
  • 369,085
  • 72
  • 557
  • 602
  • Can't you just make `$Target` mandatory and drop the default value? It would make life so much simpler :P – Frode F. Feb 27 '13 at 14:43
  • @Graimer Well, I guess I *could* do that, but optional parameters with default values are so much nicer. Also, everybody can do simple :P – poke Feb 27 '13 at 14:53
  • @poke 'but fails when the parameter is omitted' ... What's exactly fails? I'm trying your code and behave like expected.. maybe I miss something.. Have you set `Set-PSDebug -strict` ? – CB. Feb 27 '13 at 16:00
  • @C.B. Put the code into a `.ps1` and call it without specifying any parameters. It will fail with an `VariableIsUndefined` error on the `if`. (PowerShell 3 btw). – poke Feb 27 '13 at 16:02
  • @poke Ok, at the moment I'm on a v2 and I've no error, but if I do `set-psdebug -stric` I 've the error. Try to add `set-psdebug -off` maybe in v3 is ebavle by default... but IIRC is not. – CB. Feb 27 '13 at 16:05
  • @poke I've tested on a v3.0 and I've no error... try `set-psdebug -off`... somewhere you have set it to stric! – CB. Feb 27 '13 at 16:13
  • @C.B. Oh, it’s possible that I have enabled strict mode earlier to test something else! Well, what to do now… I’ll just recycle this question to ask how to solve it *in strict mode* then ;D Thank you for pointing that out though! – poke Feb 27 '13 at 16:30
  • @poke I've posted an answer for the recyled question ;) – CB. Feb 27 '13 at 16:37

1 Answers1

5

If you need run correctly in case PSDebug is running in strict mode ( set-psdebug -strict ), you can do something like this:

Param(
    [Parameter()]
    [ValidateSet('A', 'B')]
    [string] $Target = 'A'
)

DynamicParam {

    # Ensure $Target is defined
    try { [void]$Target }
    catch { $Target = [string]::Empty }

    if ($Target -eq 'B') {
        write-host "si si"
    }
}
end {
    Write-Host $Target
}
Emperor XLII
  • 13,014
  • 11
  • 65
  • 75
CB.
  • 58,865
  • 9
  • 159
  • 159