[英]Powershell binary module: Dynamic tab completion for Cmdlet parameter values
我正在用C#編寫一個二進制Powershell模塊,我想要一個帶有參數的Cmdlet,它提供動態的運行時選項卡完成。 但是,我正在努力弄清楚如何在二進制模塊中執行此操作。 這是我試圖讓這個工作:
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" };
}
}
}
這不起作用。 我沒有任何標簽完成功能。 我也收到一個錯誤:
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
我發現了一篇文章,其中有一個如何在非二進制Powershell模塊中執行此操作的示例。 在非二進制模塊中,您似乎包含DynamicParam
后跟構建和返回RuntimeParameterDictionary
對象的語句。 基於這個例子,我會期望PSCmdlet
類中的等價物,可能是一個可GetDynamicParameters()
方法或類似的東西,就像有一個可覆蓋的BeginProcessing()
方法一樣。
按照這個速度,二元模塊正在成為Powershell世界中的二等公民。 當然有一種方法可以做到這一點我錯過了嗎?
以下是在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
特別是,您需要:
IArgumentCompleter
接口。 實現此接口的類應具有公共默認構造函數。 ArgumentCompleterAttribute
屬性應用於字段的屬性,用作cmdlet參數。 作為屬性的參數,您應該傳遞IArgumentCompleter
實現。 IArgumentCompleter.CompleteArgument
您有wordToComplete
參數,因此您可以按用戶輸入的文本過濾完成選項。 嘗試一下:
Test-Completion -Name Tab
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.