我正在做一个简单的演示来说明函数中的 ArgumentCompleter 属性,这是我迄今为止正在使用的代码:
#Requires -Modules Hyper-V
#Requires -RunAsAdministrator
function Get-VMNameTest
{
param (
[ArgumentCompleter({
param ($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)
$VmNameArg = (Get-VM).Name | Where-Object {$_.Name -like "*$WordToComplete*"}
*foreach ($vm in $VmNameArg)
*{
* if ($vm -match '\s+')
* {
* "'" + $vm + "'"
* }
* else {$vm}
*}
})]
[string[]]$Name
)
foreach ($vm in $Name)
{
Write-Output "VMName: $vm"
}
}
-Name
参数将自动补全在本地计算机上找到的任何虚拟机(名称)。我添加了一个 foreach 循环(用 * 表示),以在任何包含空格的虚拟机名称周围添加单引号 - 否则,命令行上显示的虚拟机名称(包含空格)将不带引号。
当使用
CTRL + SPACE
查看自动完成值时,本机 cmdlet 在列表中显示不带单引号的值(包含空格),但是只要您在带有空格的值上使用箭头键,它就会自动添加单引号对命令行进行引号(在本例中,它使用 .\
和尾随 \
显示为路径。举例说明:PS C:\> Get-Item -Path '.\Program Files\'
$Recycle.Bin System Volume Information
Documents and Settings Users
Program Files Windows
Program Files (x86)
ProgramData
(在此示例中通过箭头键选择“程序文件”)。
这就是我的代码在 foreach 循环中的显示方式 - 单引号同时出现在列表和命令行中:
PS C:\> Get-VMNameTest -Name 'Server Two'
ServerOne 'Server Two'
PS C:\> Get-VMNameTest -Name Server Two
ServerOne Server Two
PS C:\> Get-VMNameTest -Name 'Server Two'
ServerOne Server Two
显然,本机(编译的)cmdlet 的行为方式和添加单引号(或添加路径分隔符、转义必要字符等)的逻辑存在差异。 虽然这是一个微小的外观差异,但我想知道是否有更好的方法来解决这个问题。 高手是怎么做到的?
,但是当选择一个项目时,应该加引号,如果是这种情况,那么您可以使用CompletionResult(String, String, CompletionResultType, String)
重载来完成它
:
using namespace System.Management.Automation
using namespace System.Management.Automation.Language
using namespace System.Collections
$registerArgumentCompleterSplat = @{
ParameterName = 'Test'
CommandName = 'Test-Completion'
}
Register-ArgumentCompleter @registerArgumentCompleterSplat -ScriptBlock {
param (
[string] $CommandName,
[string] $ParameterName,
[string] $WordToComplete,
[CommandAst] $CommandAst,
[IDictionary] $FakeBoundParameters
)
# generate a list of items here for testing,
# some can have spaces, others dont
$list = 0..10 | ForEach-Object { if ($_ % 2) { return "Item $_" }; "Item$_" }
# completion logic
foreach ($item in $list) {
if (-not $item.StartsWith($wordToComplete, [StringComparison]::InvariantCultureIgnoreCase)) {
continue
}
$completionText = [CodeGeneration]::EscapeSingleQuotedStringContent($item)
# if this item has white space
if ($item -match '\s') {
$completionText = "'" + $completionText + "'"
}
[CompletionResult]::new(
$completionText,
$item,
[CompletionResultType]::ParameterValue,
'some tooltip here if you want')
}
}
function Test-Completion {
param(
[Parameter(Mandatory)]
[string] $Test
)
$Test
}