简体   繁体   中英

Use ScriptBlock as determination for Mandatory

I was hoping that I could setup a cmdlet so that it would use an environment variable for a parameter value if it exists, or otherwise prompt.

function Test-Mandatory
{
  [CmdletBinding()]
  param(
    [Parameter(Mandatory = { [string]::IsNullOrEmpty($Env:TEST_PARAM) })]
    [string]
    $foo = $Env:TEST_PARAM
  )

  Write-Host $foo
}

Unfortunately, it seems that regardless of whether or not I have a $Env:TEST_PARAM set, the cmdlet always prompts for $foo.

I could rework the validation to use [ValidateScript({ #snip #}) , but then I wouldn't get Powershell prompting for the required value anymore, should $Env:TEST_PARAM not exist. I would simply get a validation error.

So 2 questions here

  • Why can I even assign a scriptblock to Mandatory if it doesn't appear to be honored?
  • Is there a simple way to get the default PS prompting behavior given the criteria I specified?

For the second question, you can always validate the value within the script. Just set the value to the environment variable as the default value. When I tried the validation with ($foo -eq $null) it didn't work, so I switched it to ($foo -eq "") . Here is a sample I tested to get what you were asking for:

function Test-Mandatory
{
  [CmdletBinding()]
  param(
    [string] $foo = $Env:TEST_PARAM
  )
begin {
    if ($foo -eq "") { 
        $foo = Read-Host "Please enter foo: "
    }
} #end begin
process {
  Write-Host $foo
} #end process
} #end function

As for the mandatory question, I believe if you assign a default value (even if it is empty), it will satisfy the mandatory assignment. When it goes to check if the value is present, since it was assigned a value, the mandatory checks true, allowing it to move on.

Of note, this doesn't work as you would expect... I would expect $foo to be marked as mandatory only if $Env:TEST_PARAM does not exist .

However, even when $Env:TEST_PARAM exists, the shell prompts :(

function Test-Mandatory
{
  [CmdletBinding()]
  param(
    [Parameter(Mandatory = { [string]::IsNullOrEmpty($Env:TEST_PARAM) })]
    [string]
    $foo
  )

if (!$PsBoundParameters.foo) { $foo = $Env:TEST_PARAM }

  Write-Host $foo
}

FYI, here's what Microsoft had to say about it:

"It's not really a bug. Script blocks are valid attribute arguments – eg ValidateScriptBlock wouldn't work very well otherwise.
Attribute arguments are always converted to the parameter type. In the case of Mandatory – it takes a bool, and any time you convert a ScriptBlock to bool, you'll get the value $true. You never invoke a script block to do a conversion."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM