PowerShell: 在自定义代码中支持Tab键自动补全
大家好,我是码农杰克~
在PowerShell中很多Cmdlet在输入参数时按tab键就可以可以自动补全,这是怎么做到的呢?
我们先来看个PowerShell自带命令:Test-Path
在PowerShell中输入下面的命令
Test-Path -Path C:\ -PathType
然后按空格,然后按Tab键,就可以看到 -PathType 后面的值会自动补全,并且总是在限定的几个值之前循环
Test-Path -Path C:\ -PathType Container
Test-Path -Path C:\ -PathType Leaf
Test-Path -Path C:\ -PathType Any
其实在PowerShell中有不止一种方法来自动补全参数。
PowerShell默认支持的自动补全
Cmdlet名
任何被加载到当前的PowerShell host中的Cmdlet在输入时按tab键都会被自动补全,如果输入的内容有多个匹配项,则在不断按Tab键时便会在多个匹配项之间切换。
比如我们输入:
Test-
再按Tab键,就有可能会得到
Test-AppLockerPolicy
继续按Tab键就可以在下面的Cmdlet之间来回切换,直到你选中你想要的
Test-Dtc
Test-NetConnection
Test-ScriptFileInfo
Test-SvnRepository
Test-AppLockerPolicy
Test-Certificate
Test-Connection
Test-DscConfiguration
Test-FileCatalog
Test-Json
Test-KdsRootKey
Test-ModuleManifest
Test-Path
Test-PnPListItemIsRecord
Test-PnPMicrosoft365GroupAliasIsUsed
Test-PnPSite
Test-PnPTenantTemplate
Test-PSSessionConfigurationFile
Test-WSMan
当然并不是每个人的机器上都都能得到相同的结果,这取决于你当前的PowerShell中加载了那些模块。
可以使用下面的命令来查看,你的系统中输入上面的命令可以得到那些可能的Cmdlet。
Get-Command Test-*
这是一个非常有用的Cmdlet尤其是当你记不住某些Cmdlet名字的时候可以使用这个命令来查找,它支持多个通配符比如:
Get-Command *Test*Get-Command Get-*PnP*Get-Command Set-*Item*
参数名
任何已被加载的Cmdlet在输入其参数名时,按Tab键,PowerShell也可以自动补全。
比如在PowerShell中输入下面的命令:
Get-Item -
再按Tab键,就可以自动补全下面的参数名:
Get-Item -Path
不停按Tab键,就可以在不同参数之间切换。
Get-Item [-Path] [-Filter ] [-Include ] [-Exclude ] [-Force] [-Credential ] [-Stream ] []
同样如果不想让其在其它不需要的参数之间切换,可以多输入几个字母,比如:
Get-Item -Pa
再按Tab键就可以直接补全 -Path参数。
参数值
- 如果Cmdlet的参数值是某个枚举,在按Tab键的时候,PowerShell会自动补全
- 如果Cmdlet的参数值被ValidateSet所限定,按Tab键的时候,PowerShell会按照ValidateSet的限定内容自动补全
- 如果某个参数使用了ArgumentCompleter,按Tab键可以根据ArgumentCompleter的返回值自动补全
- 如果某个参数使用了ArgumentCompletions,按Tab键可以根据ArgumentCompletions的内容自动补全,但是和ValidateSet的区别是ArgumentCompletions并不验证,而且也不限定用户输入只在给定的范围。所以ArgumentCompletions更多的像是建议值,而ValidateSet是限定值。
各种操作符
PowerShell中的各种操作符按Tab键也是可以自动补全的。由于PowerShell中有些符号具有特殊含义,所以PowerShell中有些运算符并不想其它语言一样使用简单符号来表示。比如表示"并且",其它语言可能使用 "&&" 但是PowerShell中使用 "-and".
例如在PowerShell中输入:
1..5 -con
再按Tab键就可以得到
1..5 -contains
然后接着输入
1..5 -contains 3#结果: True
-contains 是一个非常有用的操作符,用来判断输入是否包含目标子集。
更多操作符请参见:
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_operators?view=powershell-7.2
变量名
在PowerShell中只需要输入变量名的开头,再按Tab键也是可以自动补全的。变量分为系统默认变量、自动变量和用户自定义变量。
系统默认变量/自动变量
自动变量是在一些上下文中PowerShell为我们自动生成并赋值的变量
系统默认变量就是一些PowerShell启动之后系统自动生成的变量
比如:
$HOME$PSScriptRoot
可以使用 Get-Variable来查看,当然这个命令查看的不仅是系统变量,用户自定义变量也能看到。比如刚刚启动PowerShell的时候调用这个命令就能看到系统都有那些自动生成的变量。
Get-Variable
这些命令在PowerShell中可以直接引用,并且输入开始几个字母之后按Tab键就可以自动补全。
比如输入:
$Verbose
按Tab键就可以补全下面的变量名
$VerbosePreference
这里一定要记住使用Get-Variable得到的变量名是不带'$'符号的,我们在使用的时候要在前面加个'$'。比如上面的例子。
用户自定义变量
自定义变量就是在PowerShell窗口中用户自己定义的变量。
例如:
$processes=Get-Process
这里声明了一个变量叫"processes"并且用Get-Process的结果为其赋值。
那么我们如果要引用它,方式跟系统变量也是一样的,输入几个首字母再按Tab键,PowerShell就会自动补全剩下的变量名。
$pro
按Tab键
$processes
通过Get-Variable也能查看到刚刚声明的变量
那么如果我们在自己编写Cmdlet的时候如何使用PowerShell的自动补全功能呢?
在自定义Cmdlet中支持自动补全
Cmdlet名/参数名的自动补全
自定义的Cmdlet在导入当前的PowerShell session之后,在使用时按Tab键PowerShell就会自动补全Cmdlet名以及参数名
参数值的自动补全
自定义方法或者Cmdlet中自动补全参数值有多种方法,下面是常用的几种方式。
使用枚举
如果我们Cmdlet参数限定为枚举类型,那么我们按Tab键的时候,PowerShell会自动获取对应枚举类型的名字为我们补全值。
比如Write-Host中设置字体颜色或者背景颜色
Write-Host
[[-Object] ]
[-NoNewline]
[-Separator ]
[-ForegroundColor ]
[-BackgroundColor ]
[]
我们可以看到-ForegroundColor和-BackgroundColor均为[ConsoleColor]这个枚举类型,所以当我们想设置字体颜色的时候输入 -ForegroundColor再按Tab键,PowerShell就会自动提取[ConsoleColor]这个枚举的所有值供我们选择啦。
运行下面的命令:
[ConsoleColor]::GetNames([ConsoleColor])
可以看到这个枚举类型有下面这些值:
BlackDarkBlueDarkGreenDarkCyanDarkRedDarkMagentaDarkYellowGrayDarkGrayBlueGreenCyanRedMagentaYellowWhite
那如果输入:
Write-Host "red" -ForegroundColor R
再按一下Tab键,就可以自动补全成下面的命令了:
Write-Host "red" -ForegroundColor Red
使用ValidateSetAttribute
如果没有合适枚举类型,或者嫌声明枚举类型太过麻烦,还可以使用ValidateSetAttribute。ValidateSetAttribute,既限定了参数的可能值,也会做相应的验证,如果输入值不在它定义的范围内则会抛错。
具体使用见下面代码:
function Test-Foo{ param( [ValidateSet("Jerry","Tom")] [string] $Name ) Write-Host "I'm $Name." #... Function body here}
在PowerShell中运行上面的代码,然后就可以调用Test-Foo了。当然输入参数-Name 时PowerShell就会根据ValidateSet里面的可能值进行自动补全。
输入:
Test-Foo -Name
然后按Tab键得到补全后的命令:
Test-Foo -Name Jerry# I'm Jerry.
使用ArgumentCompletionsAttribute
使用ArgumentCompletions属性可以在用户按Tab键时给一系列的建议值。但是并不验证和限定用户的输入。这是他和ValidateSet属性的区别,ValidateSet属性不仅验证用户输入,而且还限定用户的输入必须在给定的集合内。
function Test-ArgumentCompletions {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[ArgumentCompletions('Fruits', 'Vegetables')]
$Type,[Parameter()]
[ArgumentCompletions('Apple', 'Banana', 'Orange')]
$Fruit,[Parameter()]
[ArgumentCompletions('Tomato', 'Corn', 'Squash')]
$Vegetable
)
}
在PowerShell中运行上面的代码,然后在输入:
Test-ArgumentCompletions -Fruit
按Tab键,就可以自动补全参数值,并且PowerShell会从'Apple', 'Banana', 'Orange'这几个值当中依次选取选取。
使用ArgumentCompleterAttribute
ArgumentCompleter提供了更加强大的方式来自动补全用户输入。ArgumentCompleter中需要用户编写相应的脚本或者类来实现自动补全的逻辑。
ArgumentCompleter中的脚本有5个参数:
$commandName
正在使用自动补全的对应的Cmdlet名字.$parameterName
正在使用自动补全的参数名.$wordToComplete
用户在按Tab键以前已经输入的值,比如 如果输入"Write-Host -ForegroundColor R" 那么这个$wordToComplete
的值就等于 "R",然后就可以在代码里面决定如何匹配对应的参数值了. 比如"Red".$commandAst
(Position 3) - 当前命令行里已经输入的内容比如:"Write-Host -ForegroundColor R". 这个参数非常有用,有时候可以使用这个参数对自动完成的内容做更多的判断。 更多内容请参考 AST .$fakeBoundParameters
(Position 4) - 用户按Tab键以前已经输入的参数以及值。参考 about_Automatic_Variables.
因此上一节中ArgumentCompletions还可以修改为下面的代码。
function MyArgumentCompleter{
param ( $commaName,
$parameterName,
$wordToComplete,
$commandAst,
$fakeBoundParameters )$possibleValues = @{
Fruits = @('Apple', 'Orange', 'Banana')
Vegetables = @('Tomato', 'Squash', 'Corn')
}if ($fakeBoundParameters.ContainsKey('Type')) {
$possibleValues[$fakeBoundParameters.Type] | Where-Object {
$_ -like "$wordToComplete*"
}
} else {
$possibleValues.Values | ForEach-Object {$_}
}
}function Test-ArgumentCompleter {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[ValidateSet('Fruits', 'Vegetables')]
$Type,[Parameter(Mandatory=$true)]
[ArgumentCompleter({ MyArgumentCompleter @args })]
$Value
)
}
ArgumentCompletions和ArgumentCompleter这两者没有孰优孰劣,只是具体使用场景不同,ArgumentCompletions使用简单方便,ArgumentCompleter使用灵活,可以自定义补全逻辑。
使用PowerShell的Prediction功能
这个需要PowerShell5.1以上版本才能支持。
在PowerShell中运行以下命令:
Set-PSReadLineOption -PredictionSource History
然后就可以看到,我们任何在PowerShell里面输入过的命令都可以轻松的重新输入了。比如之前我输入过的Write-Host例子。当我在PowerShell中输入两个字母“wr”时,PowerShell自动提示我之前输入过的命令:
然后按方向键的向右键-> 之前输入过的命令就自动补全了。
关于这个设置的更多内容请参考:PowerShell: 为啥大神们的PowerShell窗口还有智能提示?因为他设置了这个_码农杰克-CSDN博客
总结
熟悉和使用PowerShell的自动补全功能,可以提高我们的工作效率。同时也可以写出更加易用的PowerShell脚本,以提高工作效率。
大家好,我是码农杰克~
希望上面的介绍对你有所帮助,有PowerShell的问题都可以和我探讨。