Если я наберу в командной строке:
[pscustomobject]@{ name = 'test'; description='doing test' } | Select-Object
Я могу нажать клавишу Tab и заполнить имена свойств — помимо свойств по умолчанию, любое из определенных свойств name
и description
. Select-Object
знает о свойствах name
и description
входного объекта и автоматически заполняет их со стандартным поведением вкладки.
Теперь, если я использую пользовательскую функцию, например:
function pipeobject {
param(
[Parameter(ValueFromPipeline)]
$InputObject,
[Parameter(Position=0)]
$Property
)
process {
$Property | Foreach-Object { $InputObject.$_ }
}
}
и введите:
[pscustomobject]@{ name = 'test'; description='doing test' } | pipeobject
Я не могу заполнить параметр -Property
с помощью табуляции ни для одного из свойств входного объекта.
Примечание. Мне известен этот ответ, в котором рекомендуется использовать типы вывода. Однако мой запрос относится к анализу свойств универсального pscustomobject, который Select-Object
кажется способен на это.
Как я могу воспроизвести поведение завершения табуляции Select-Object
в конвейере для свойств в моих пользовательских функциях?
То, что вы описываете, выведение участников из pscustomobject
из конвейера, является одним из многих замечательных улучшений завершения табуляции в PowerShell v7.4 от MartinGC94 (в данном случае PR #18682 ), и краткий ответ: вы не найдете простого способа надежно повторить то, что он сделал, но для начала следует показать вам, как можно подойти к проблеме, взглянув на CommandAst:
Register-ArgumentCompleter -CommandName pipeobject -ParameterName Property -ScriptBlock {
param(
[string] $CommandName,
[string] $ParameterName,
[string] $WordToComplete,
[System.Management.Automation.Language.CommandAst] $CommandAst,
[System.Collections.IDictionary] $FakeBoundParameters
)
$ast = $CommandAst.Parent.FindAll({
$args[0] -is [System.Management.Automation.Language.ConvertExpressionAst] },
$true)
if (-not $ast.Child.KeyValuePairs) {
return
}
$hash = [System.Collections.Generic.HashSet[string]]::new(
[System.StringComparer]::InvariantCultureIgnoreCase)
foreach ($item in $ast.Child.KeyValuePairs.Item1) {
$key = $item.ToString()
if (-not $hash.Add($key)) {
continue
}
if ($key.StartsWith($WordToComplete, [StringComparison]::InvariantCultureIgnoreCase)) {
$item
}
}
}
@mklement0 готово, пояснил, что это из 7.4, хотя ссылка уже была там. также я предпочитаю использовать StartsWith + Hashset в этом случае.