【发布时间】:2015-10-14 17:37:12
【问题描述】:
我正在用 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
我发现an article 有一个如何在非二进制 Powershell 模块中执行此操作的示例。在非二进制模块中,您似乎包含DynamicParam,后跟构建并返回RuntimeParameterDictionary 对象的语句。基于这个例子,我预计 PSCmdlet 类中的等价物,可能是一个可覆盖的 GetDynamicParameters() 方法或类似的东西,就像有一个可覆盖的 BeginProcessing() 方法一样。
按照这个速度,二进制模块正在 Powershell 世界中成为二等公民。肯定有一种我错过的方法吗?
【问题讨论】:
-
我相信您至少需要将IDynamicParameters 接口添加到您的cmdlet 以使用动态参数。从那里我相信你会做与示例中相同的事情(创建一个 RuntimeParameterDictionary 等)但是我无法确认这一点。
-
IDynamicParameters 会让您在运行时确定参数,但我相信 OP 是在询问是否提供动态参数 values。
标签: c# powershell powershell-module