3

C# でバイナリ Powershell モジュールを作成しています。動的な実行時のタブ補完を提供するパラメーターを含むコマンドレットが必要です。ただし、バイナリモジュールでこれを行う方法を理解するのに苦労しています。これを機能させるための私の試みは次のとおりです。

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類似のクラスで同等のものを期待します。PSCmdletGetDynamicParameters()BeginProcessing()

このままでは、バイナリ モジュールは Powershell の世界では二流の市民になりそうです。確かに私が見逃したこれを行う方法はありますか?

4

1 に答える 1

10

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コマンドレット パラメーターとして使用されるフィールドのプロパティに属性を適用します。属性へのパラメーターとして、IArgumentCompleter実装を渡す必要があります。
  • パラメータがあるため、ユーザーがすでに入力したテキストで補完オプションをフィルタリングできIArgumentCompleter.CompleteArgumentます。wordToComplete

そしてそれを試すには:

テスト完了 - 名前Tab
于 2015-10-14T23:07:28.073 に答える