PowerShell|当具有所需条件的文件不在当前工作目录中时,参数完成符不起作用

mnemlml8  于 2023-06-06  发布在  Shell
关注(0)|答案(1)|浏览(320)

到目前为止,我已经尝试了2个参数完成器,当我按Tab按钮时,my module只显示扩展名为.cer的文件。
这是其中的一个

$ArgumentCompleterCertPath = {
    Get-ChildItem | where-object { $_.extension -like '*.cer' } | foreach-object { return "`"$_`"" }   
}
Register-ArgumentCompleter -CommandName "Edit-SignedWDACConfig" -ParameterName "CertPath" -ScriptBlock $ArgumentCompleterCertPath

这是另一个

[ArgumentCompleter({
            param($commandName, $parameterName, $wordToComplete, $commandAst)
      
            # Get the current path from the command
            $path = $commandAst.CommandElements |
              Where-Object { $_.ParameterName -eq 'Path' } |
              Select-Object -ExpandProperty Argument
      
            # Resolve the path to a full path
            $resolvedPath = Resolve-Path -LiteralPath $path
      
            # Get the files with .cer extension in the resolved path
            $files = Get-ChildItem -LiteralPath $resolvedPath -Filter *.cer
      
            # Create an array of completion results from the file names
            $completions = foreach ($file in $files) {
              [System.Management.Automation.CompletionResult]::new($file.Name, $file.Name, 'ParameterValue', $file.Name)
            }
      
            # Return the completions
            return $completions
          })]

当当前目录中有证书文件时,它们都可以工作,但如果没有证书文件,当我按Tab时,它们会建议使用任何扩展名的任何文件,甚至文件夹。
我想从他们那里得到的是:
1.如果没有任何文件满足参数完成器的条件,则不显示错误的文件
1.如果当前工作目录不包含任何符合参数完成器条件的文件,则递归搜索子目录以找到好的文件,即使递归搜索没有找到任何文件,也不会在按Tab时显示错误的文件。
对于我的具体情况,我将证书文件放在当前工作目录的第二子目录中。
我试着加上

Get-ChildItem -Recurse -ErrorAction 'SilentlyContinue'

但这并没有解决问题

7bsow1i6

7bsow1i61#

  • 默认情况下,每当 * 自定义 * 完成器不返回任何内容**(从技术上讲,这是[System.Management.Automation.Internal.AutomationNull]::Value单例)时,PowerShell * 福尔斯 * 其 * 默认 * 制表符完成,这使其执行当前目录中所有文件和子目录名称的常规完成。
    *如果返回$null,则可以 * 抑制 * 此回退行为,这样,如果您的自定义补全器未找到匹配项,则根本不会提供补全。
    *警告:从PowerShell 7.3.4开始,这似乎
    只适用于Register-ArgumentCompleter调用**,而不是使用 * 脚本块 * 的参数单独ArgumentCompleter属性,不清楚这是否是官方支持的机制,或者是否有一个
  • 参见GitHub issue #19628
  • 然而,正如Santiago Squarzon所发现的,如果您**将ArgumentCompleter属性 * 与实现IArgumentCompleter***的自定义类一起使用,而不是与 * 脚本块一起使用,回退 * 也可以 * 被阻止
  • 事实上,逻辑是“颠倒”的:使用return $null作为一个 * 选择加入 * 回退到默认完成。
  • 参见圣地亚哥的示例代码。
  • 从PowerShell 7.3.4开始:
  • PowerShell的默认制表符完成过于热心,因为它执行文件/目录名完成,即使对于参数类型也没有任何意义(例如[int])-参见GitHub issue #14147
  • 正如圣地亚哥所指出的,在制表符完成器中实现Get-ChildItem -Recurse的无约束使用是有问题的,因为它可能导致潜在的冗长操作;但是,您可以使用-Depth参数将递归限制为固定的深度。
  • 例如,-Depth 1将查找限制为输入目录本身及其 immediate 子目录的内容。

因此,请尝试以下操作:

$ArgumentCompleterCertPath = {
  # Note the use of -Depth 1
  # Enclosing the $results = ... assignment in (...) also passes the value through.
  ($results = Get-ChildItem -Depth 1 -Filter *.cer | foreach-object {  "`"$_`"" })
  if (-not $results) { # No results?
    $null # Dummy response that prevents fallback to the default file-name completion.
  } 
}
Register-ArgumentCompleter -CommandName "Foo" -ParameterName "CertPath" -ScriptBlock $ArgumentCompleterCertPath

相关问题