Being able to pass script blocks ad hoc in order to calculate per-input-object parameter values is a great general-purpose feature.
However, it is currently limited to parameters that are explicitly defined as pipeline-binding.
A widely used application of this technique is with Rename-Item's -NewName parameter, where a script block is passed to calculate the new name; e.g.:
# Rename all *.rtf files to *.txt files
Get-Item *.rtf | Rename-Item -NewName { $_.BaseName + '.txt' } -WhatIf
However, the above only works because -NewName too is defined as pipeline-binding (ValueFromPipelineByPropertyName, in this case).
The ability to pass a script block to any parameter (other than those typed [object] or [scriptblock]) of a command that accepts pipeline input in principle - whether or not that parameter is itself pipeline-binding - would make this technique useful in a much wider array of situations.
Is there a conceptual barrier to removing this restriction (overall, the cmdlet/advanced function would still have to have at least one pipeline-binding parameter)?
Technically, this would be a breaking change, albeit hopefully one that falls into Bucket 3: Unlikely Grey Area:
What happens currently if you try to pass a script block to a differently typed non-pipeline-binding parameters is that an attempt is made to convert the script block to the parameter's type (unless the parameter is [object] or [scriptblock], which would continue to be exempt).
This fails with most types, but in the case of a [string] parameter you currently do get the script block's contents as a string value.
Arguably, though, users who expect script blocks type their parameters a such.
Here's an example with an advanced function:
function Rename-Foo {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[System.IO.FileSystemInfo] $InputObject
,
# WISHFUL THINKING: The `ValueFromPipelineByPropertyName` shouldn't be necessary.
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
[string] $NewName
)
process {
"Will rename $($InputObject.Name) to $NewName."
}
}
PS> Get-Item foo.txt, bar.txt | Rename-Foo -NewName { $_.Name + '!!' }
Will rename foo.txt to foo.txt!!
Will rename bar.txt to bar.txt!!
Environment data
Written as of:
Being able to pass script blocks ad hoc in order to calculate per-input-object parameter values is a great general-purpose feature.
However, it is currently limited to parameters that are explicitly defined as pipeline-binding.
A widely used application of this technique is with
Rename-Item's-NewNameparameter, where a script block is passed to calculate the new name; e.g.:However, the above only works because
-NewNametoo is defined as pipeline-binding (ValueFromPipelineByPropertyName, in this case).The ability to pass a script block to any parameter (other than those typed
[object]or[scriptblock]) of a command that accepts pipeline input in principle - whether or not that parameter is itself pipeline-binding - would make this technique useful in a much wider array of situations.Is there a conceptual barrier to removing this restriction (overall, the cmdlet/advanced function would still have to have at least one pipeline-binding parameter)?
Technically, this would be a breaking change, albeit hopefully one that falls into Bucket 3: Unlikely Grey Area:
What happens currently if you try to pass a script block to a differently typed non-pipeline-binding parameters is that an attempt is made to convert the script block to the parameter's type (unless the parameter is
[object]or[scriptblock], which would continue to be exempt).This fails with most types, but in the case of a
[string]parameter you currently do get the script block's contents as a string value.Arguably, though, users who expect script blocks type their parameters a such.
Here's an example with an advanced function:
Environment data
Written as of:
PowerShell Core v6.0.2