我有一个 PowerShell 7.1 帮助程序脚本,用于将项目从 subversion 复制到本地设备。我希望通过启用 PowerShell 将参数自动补全到此脚本中来使此脚本更易于使用。经过一些研究,看起来我可以实现一个接口来通过 ValidateSet 提供有效参数。
\n根据微软的文档,我尝试这样做:
\n[CmdletBinding()]\nparam (\n    [Parameter(Mandatory)]\n    [ValidateSet([ProjectNames])]\n    [String]\n    $ProjectName,\n\n    #Other params\n)\n\nClass ProjectNames : System.Management.Automation.IValidateSetValuesGenerator {\n    [string[]] GetValidValues() {\n        # logic to return projects here.\n    }\n}\nRun Code Online (Sandbox Code Playgroud)\n当我运行它时,它不会自动完成,并且出现以下错误:
\n\xe2\x9d\xaf Copy-ProjectFromSubversion.ps1 my-project\nInvalidOperation: C:\\OneDrive\\Powershell-Scripts\\Copy-ProjectFromSubversion.ps1:4\nLine |\n   4 |      [ValidateSet([ProjectNames])]\n     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n     | Unable to find type [ProjectNames].\nRun Code Online (Sandbox Code Playgroud)\n这是有道理的,因为类在参数之后才被定义。所以我将类移到了参数上方。显然这是一个语法错误。那么我该怎么做呢?在简单的 PowerShell 脚本中不可能吗?
\nmkl*_*nt0 13
事实上,您遇到了第 22 条军规:要使参数声明在脚本解析阶段起作用,[ProjectNames]必须已经定义类,但不允许将类定义放在参数声明之前。
使用独立脚本文件 ( )最接近您的意图的.ps1是使用该ValidateScript属性:
[CmdletBinding()]
param (
  [Parameter(Mandatory)]
  [ValidateScript(
    { $_ -in (Get-ChildItem -Directory).Name },
    ErrorMessage = 'Please specify the name of a subdirectory in the current directory.'
  )]
  [String] $ProjectName # ...
)
Run Code Online (Sandbox Code Playgroud)
限制:
[ValidateScript]没有也不能提供制表符补全:脚本块, { ... },提供的验证仅期望返回Boolean,并且不能保证甚至涉及一组离散值。
同样,您无法在属性值中引用动态生成的有效值集(在脚本块内生成)ErrorMessage。
解决这些限制的唯一方法是复制计算有效值的脚本块部分,但这可能会成为维护难题。
要获得制表符完成功能,您必须在[ArgumentCompleter]属性中复制代码的相关部分:
[CmdletBinding()]
param (
  [Parameter(Mandatory)]
  [ValidateScript(
    { $_ -in (Get-ChildItem -Directory).Name },
    ErrorMessage = 'Please specify the name of a subdirectory in the current directory.'
  )]
  [ArgumentCompleter(
    {
      param($cmd, $param, $wordToComplete)
      # This is the duplicated part of the code in the [ValidateScipt] attribute.
      [array] $validValues = (Get-ChildItem -Directory).Name
      $validValues -like "$wordToComplete*"
    }
  )]
  [String] $ProjectName # ...
)
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           4084 次  |  
        
|   最近记录:  |