Подтвердить что ты не робот

Взаимоисключающие параметры powershell

СЦЕНАРИЙ

  • Я пишу командлет для Powershell 2.0 с помощью Visual Studio 2008 и .NET 3.5
  • Командлет требует 3 аргумента.

моя предполагаемая грамматика командлета выглядит примерно так:

cmdletname [foo|bar] p1, p2
  • Это означает, что пользователь должен указать значение для "-foo" или "-bar", но не может давать оба вместе.

ПРИМЕР ДЕЙСТВИТЕЛЬНОГО ВХОДА

cmdletname -foo xxx -p1 hello  -p2 world
cmdletname -bar yyy -p1 hello  -p2 world

ПРИМЕР НЕПРЕРЫВНОГО ВХОДА

cmdletname -foo xxx -bar yyy -p1 hello  -p2 world

МОЙ ВОПРОС

  • Мой вопрос в том, как это сделать в powershell, чтобы он выполнял все проверки для меня - или, если это вообще возможно.
  • Я знаю, что могу использовать только два необязательных параметра для foo и bar и просто выполнить проверку ошибок вручную. Это то, как я это сделал в настоящее время.
  • В качестве альтернативы меня интересуют предложения по различным подходам.
4b9b3361

Ответ 1

Здесь приведен пример использования ParameterSetName, взятый из командлета в Расширения сообщества PowerShell. BTW, для идей вы можете просмотреть исходный код PSCX.

[Cmdlet(VerbsCommon.Set, PscxNouns.Clipboard, 
        DefaultParameterSetName = ParamSetText)]
[Description("Copies the item in the system clipboard.")]
[RelatedLink(typeof(GetClipboardCommand))]
[RelatedLink(typeof(OutClipboardCommand))]
[RelatedLink(typeof(WriteClipboardCommand))]
public class SetClipboardCommand : ClipboardCommandBase
{
    ... fields elided

    const string ParamSetRtf = "Rtf";
    const string ParamSetHtml = "Html";
    const string ParamSetText = "Text";
    const string ParamSetFiles = "Files";
    const string ParamSetImage = "Image";
    . 
    [AllowNull]
    [Parameter(ValueFromPipeline = true, ParameterSetName = ParamSetImage)]
    public Image Image { get; set; }
    . 
    [AllowNull]
    [AllowEmptyCollection]
    [Parameter(ValueFromPipeline = true, ValueFromRemainingArguments = true,
               ParameterSetName = ParamSetFiles)]
    public FileSystemInfo[] Files { get; set; }
    . 
    [AllowNull]
    [AllowEmptyString]
    [Parameter(ValueFromPipeline = true, ValueFromRemainingArguments = true,
               ParameterSetName = ParamSetText)]
    public string Text { get; set; }
    . 
    [Parameter(ValueFromPipeline = true, ValueFromRemainingArguments = true,
               ParameterSetName = ParamSetHtml)]
    public string Html { get; set; }
    .         
    [Parameter(ValueFromPipeline = true, ValueFromRemainingArguments = true,
               ParameterSetName = ParamSetRtf)]
    public string Rtf { get; set; }
    . 
    protected override void ProcessRecord()
    {
        ...
    }
    .
    protected override void EndProcessing()
    {
        ExecuteWrite(delegate
        {
            switch (ParameterSetName)
            {
                case ParamSetFiles:
                    if (Paths.Count == 0)
                        WinFormsClipboard.Clear();
                    else
                        WinFormsClipboard.SetFileDropList(_paths);
                    break;

                case ParamSetImage:
                    if (Image == null)
                        WinFormsClipboard.Clear();
                    else
                        WinFormsClipboard.SetImage(_image);
                    break;

                case ParamSetRtf:
                    SetTextContents(Rtf, TextDataFormat.Rtf);
                    break;

                case ParamSetHtml:
                    SetTextContents(Html, TextDataFormat.Html);
                    break;

                default:
                    SetTextContents(Text, TextDataFormat.UnicodeText);
                    break;
            }
        });
    }
    ...
}

Обратите внимание, что командлет обычно объявляет значение ParameterSetName по умолчанию, которое помогает PowerShell определить параметр "по умолчанию", который используется, когда есть двусмысленность. Позже, если необходимо, вы можете определить, какой набор параметров находится в силе, запросив это. Параметр ParameterSetName как оператор switch делает выше в переопределении EndProcessing().

Ответ 2

Вы можете использовать атрибут для объявления нескольких наборов параметров. Затем вы просто назначаете параметры, которые являются взаимоисключающими для разных наборов параметров.

EDIT:

Это также описано в разделе "about_Functions_Advanced_Parameters" в разделе "ParameterSetName Named Argument". Вот как обрабатываются различные параметры параметров с помощью командлетов типа Get-Random (которые имеют взаимоисключающие параметры):

> get-random -input 4 -max 77
Get-Random : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:11
+ get-random <<<<  -input 4 -max 77
    + CategoryInfo          : InvalidArgument: (:) [Get-Random], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.GetRandomCommand

Вот пример выполнения этой функции:

function exclusive_params() { 
    param( 
        [parameter(ParameterSetName="seta")]$one,
        [parameter(ParameterSetName="setb")]$two, 
        $three 
    )
    "one: $one"; "two: $two"; "three: $three" 
}

Параметры one и two находятся в разных наборах параметров, поэтому они не могут быть указаны вместе:

> exclusive_params -one foo -two bar -three third
exclusive_params : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:17
+ exclusive_params <<<<  -one foo -two bar -three third
    + CategoryInfo          : InvalidArgument: (:) [exclusive_params], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,exclusive_params

Какую же ошибку я получил с Get-Random. Но я могу использовать параметры самостоятельно:

> exclusive_params -one foo -three third
one: foo
two:
three: third

... или:

> exclusive_params -two bar -three third
one:
two: bar
three: third