[英]Powershell binary module: Dynamic tab completion for Cmdlet parameter values
I'm writing a binary Powershell module in C# and I'd like to have a Cmdlet with a parameter that provides dynamic, run-time tab completion. 我正在用C#编写一个二进制Powershell模块,我想要一个带有参数的Cmdlet,它提供动态的运行时选项卡完成。 However, I'm struggling to figure out how to do this in a binary module. 但是,我正在努力弄清楚如何在二进制模块中执行此操作。 Here's my attempt to get this working: 这是我试图让这个工作:
using System;
using System.Collections.ObjectModel;
using System.Management.Automation;
namespace DynamicParameterCmdlet
{
[Cmdlet("Say", "Hello")]
public class MyCmdlet : PSCmdlet
{
[Parameter, PSTypeName("string")]
public RuntimeDefinedParameter Name { get; set; }
public MyCmdlet() : base() {
Collection<Attribute> attributes = new Collection<Attribute>() {
new ParameterAttribute()
};
string[] allowedNames = NameProvider.GetAllowedNames();
attributes.Add(new ValidateSetAttribute(allowedNames));
Name = new RuntimeDefinedParameter("Name", typeof(string), attributes);
}
protected override void ProcessRecord()
{
string name = (string)Name.Value;
WriteObject($"Hello, {Name}");
}
}
public static class NameProvider
{
public static string[] GetAllowedNames()
{
// Hard-coded array here for simplicity but imagine in reality this
// would vary at run-time
return new string[] { "Alice", "Bob", "Charlie" };
}
}
}
This doesn't work. 这不起作用。 I don't get any tab completion functionality. 我没有任何标签完成功能。 I also get an error: 我也收到一个错误:
PS > Say-Hello -Name Alice
Say-Hello : Cannot bind parameter 'Name'. Cannot convert the "Alice" value of type "System.String" to type "System.Management.Automation.RuntimeDefinedParameter".
At line:1 char:17
+ Say-Hello -Name Alice
+ ~~~~~
+ CategoryInfo : InvalidArgument: (:) [Say-Hello], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,DynamicParameterCmdlet.MyCmdlet
I've found an article with an example of how to do it in a non-binary Powershell module. 我发现了一篇文章,其中有一个如何在非二进制Powershell模块中执行此操作的示例。 It seems in non-binary modules you include DynamicParam
followed by statements that build and return a RuntimeParameterDictionary
object. 在非二进制模块中,您似乎包含DynamicParam
后跟构建和返回RuntimeParameterDictionary
对象的语句。 Based on this examplem I would at expect the equivalent in the PSCmdlet
class, perhaps an overridable GetDynamicParameters()
method or something similiar, just as there is an overridable BeginProcessing()
method. 基于这个例子,我会期望PSCmdlet
类中的等价物,可能是一个可GetDynamicParameters()
方法或类似的东西,就像有一个可覆盖的BeginProcessing()
方法一样。
At this rate, binary modules are looking to be second-class citizens in the Powershell world. 按照这个速度,二元模块正在成为Powershell世界中的二等公民。 Surely there is a way to do this that I've missed? 当然有一种方法可以做到这一点我错过了吗?
Here is a way how you can implement custom argument completer in PowerShell v5: 以下是在PowerShell v5中如何实现自定义参数完成的方法:
Add-Type @‘
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Language;
[Cmdlet(VerbsDiagnostic.Test,"Completion")]
public class TestCompletionCmdlet : PSCmdlet {
private string name;
[Parameter,ArgumentCompleter(typeof(NameCompleter))]
public string Name {
set {
name=value;
}
}
protected override void BeginProcessing() {
WriteObject(string.Format("Hello, {0}", name));
}
private class NameCompleter : IArgumentCompleter {
IEnumerable<CompletionResult> IArgumentCompleter.CompleteArgument(string commandName,
string parameterName,
string wordToComplete,
CommandAst commandAst,
IDictionary fakeBoundParameters) {
return GetAllowedNames().
Where(new WildcardPattern(wordToComplete+"*",WildcardOptions.IgnoreCase).IsMatch).
Select(s => new CompletionResult(s));
}
private static string[] GetAllowedNames() {
return new string[] { "Alice", "Bob", "Charlie" };
}
}
}
’@ -PassThru|Select-Object -First 1 -ExpandProperty Assembly|Import-Module
In particular, you need: 特别是,您需要:
IArgumentCompleter
interface. 实现IArgumentCompleter
接口。 Class implementing this interface should have public default constructor. 实现此接口的类应具有公共默认构造函数。 ArgumentCompleterAttribute
attribute to property of field, used as cmdlet parameter. 将ArgumentCompleterAttribute
属性应用于字段的属性,用作cmdlet参数。 As parameter to attribute, you should pass IArgumentCompleter
implementation. 作为属性的参数,您应该传递IArgumentCompleter
实现。 IArgumentCompleter.CompleteArgument
you have wordToComplete
parameter, so you can filter completion options by text, already inputted by user. 在IArgumentCompleter.CompleteArgument
您有wordToComplete
参数,因此您可以按用户输入的文本过滤完成选项。 And to try it: 尝试一下:
Test-Completion -Name Tab
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.