Powershell 我不知道';无法理解带有begin/process/end块的函数上的参数绑定

Powershell 我不知道';无法理解带有begin/process/end块的函数上的参数绑定,powershell,Powershell,我这样称呼它,假设我已经在字典中添加了值(为了简洁起见,这里删除了) 这是我的难题 上述方法非常有效。但是,下面没有说明key/value参数中的差异 $dict = New-Object 'System.Collections.Generic.Dictionary[string,string]' $dict.GetEnumerator() | Format-File -Path $updatePath 上面抛出了一个异常。第一次调用函数时,它似乎获得默认值,但在处理时,键/值参数设置正确 为

我这样称呼它,假设我已经在字典中添加了值(为了简洁起见,这里删除了)

这是我的难题

上述方法非常有效。但是,下面没有说明key/value参数中的差异

$dict = New-Object 'System.Collections.Generic.Dictionary[string,string]'
$dict.GetEnumerator() | Format-File -Path $updatePath
上面抛出了一个异常。第一次调用函数时,它似乎获得默认值,但在处理时,键/值参数设置正确

为什么不在函数调用时设置键/值,这有点道理,但这也意味着我的心智模型已关闭

所以我的问题是双重的

  • 这种性质的函数的参数绑定过程是什么
  • 如何验证从管道中输入的值?手动签入开始块,或者是否有其他方法
  • 如果你有更详细描述这一切的链接,我很乐意阅读。这让我意识到我的心理模型是有缺陷的,我希望能解决这个问题。

    这种性质的函数的参数绑定过程是什么? 在
    Begin
    块中,管道绑定参数将为
    $null
    ,如果有,则使用其默认值。考虑到价值的管道化还没有开始,这是有道理的

    过程
    块中,参数将是管道中的当前项

    结束
    块中,参数将是
    过程
    块中的最后一个值,除非验证参数时出现异常,在这种情况下,它将使用默认值(或
    $null

    如何验证从管道中输入的值? 无法签入
    开始

    最好的方法是使用
    [Validate
    属性,就像使用
    [ValidateNotNullOrEmpty()]
    一样

    使用
    throw
    作为默认值的示例在某些情况下很有用,但它们是一种巧妙的解决方法。问题是,您不需要它们,因为您已经将参数声明为必需参数

    例如,您可以使用
    [ValidateScript({$value-eq'MyString'})]
    而不是使用默认值

    由于来自
    [ValidateScript()]
    的错误消息很糟糕,您可以结合使用以下技术:

    函数格式文件{
    param(
    [参数(必需=$true,位置=1,ValueFromPipelineByPropertyName=$true)]
    [ValidateNotNullOrEmpty()]
    [ValidateScript({
    ($我的.Length-le 10)-或$(抛出“我的自定义异常消息”)
    } )]
    [字符串]$key
    )
    }
    

    无论是否为管道参数,使用
    [ValidateScript()]
    都会起作用。

    管道值在
    过程中进行处理
    这就是关键所在。在此之前,您不会看到它们,因为函数启动时它们可能不存在(管道流).Validation为每个管道输入运行?这很好。亲爱的上帝,
    ValidateScript
    的错误输出很糟糕。是的,它在每个管道输入上运行。如果您使用
    -ErrorAction Stop
    (或其等效首选项)调用它当抛出异常时,它将停止,但如果没有,它将继续使用管道。ValidateScript属性是否比普通函数中的默认值技巧有任何优势,或者在处理管道输入时,它的优势更多的是在更合适的时间绑定?我想继续使用默认值技巧I在一般情况下,因为它比较短,只有在有明确的理由时才使用validatescript。我想不出具体的优势,但在发布这个问题之前,我也没有想到它在管道方面的用途。但在我看来,这是“正确方式”的继承优势。我还认为它保持了(经常是混乱的)验证代码从函数体中删除,使其更干净。我喜欢这种分离;我认为参数验证应该尽可能在声明中进行。感谢知识渊博的响应,我的powershell知识今天有了很大的提高:)
    $dict = New-Object 'System.Collections.Generic.Dictionary[string,string]'
    $dict.GetEnumerator() | Format-File -Path $updatePath
    
    function Format-File {
      param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string] $path=$(throw "path is mandatory ($($MyInvocation.MyCommand))"),
    
        [Parameter(Mandatory = $true, Position = 1, ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [string] $key=$(throw "key is mandatory ($($MyInvocation.MyCommand))"),
    
        [Parameter(Mandatory = $true, Position = 2, ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [string] $value=$(throw "value is mandatory ($($MyInvocation.MyCommand))")
      )
    }