Написание командлета PowerShell для принятия scriptblock в качестве параметра

StackOverflow https://stackoverflow.com/questions/1374451

  •  21-09-2019
  •  | 
  •  

Вопрос

Rename-Item принимает scriptblock (я думаю ...) в качестве параметра, поэтому я могу сделать что-то подобное, если я хочу переименовать кучу файлов (например):

Dir *.ps1 | Rename-item -NewName {$_.Name -replace ".ps1" ".txt" }

Я пишу командлет для переименования некоторых элементов и хотел бы иметь возможность использовать подобный синтаксис для нового имени, но как объявить параметр, чтобы он принимал подобный блок сценария или простую строку?

Это было полезно?

Решение

Если вы пишете командлет на базе .NET (C # / VB), то имейте в виду, что любой параметр, привязанный к конвейеру, будет автоматически поддерживать scriptblocks.Это всего лишь функция в PowerShell.Однако, если параметр, который вы хотите использовать, не привязан к конвейеру, вы можете сделать это:

[Parameter]
public ScriptBlock NewName { get; set; }

[Parameter(ValueFromPipeline = true)]
public string OldName { get; set; }

protected override void ProcessRecord()
{
    Collection<PSObject> results = NewName.Invoke(this.OldName);
    this.Host.UI.WriteLine("New name is " + results[0]);
}

Единственное, что мне не нравится в этом подходе, это то, что вы не можете использовать $_ в scriptblock, в этом случае вы должны использовать $args[0].Возможно, есть лучший способ сделать это, и кто-нибудь присоединится к нему.

OTOH, Rename-Item действительно указывает параметр NewName как конвейер, связанный с именем свойства.В этом случае вы просто задаете параметру NewName нужный вам тип (string) и позволяете PowerShell выполнять магию scriptblock.Лучше всего, в этом случае $_ работает в скриптоблоке, например:

[Parameter(ValueFromPipelineByPropertyName = true)]
public string NewName { get; set; }

[Parameter(ValueFromPipeline = true)]
public string OldName { get; set; }

protected override void ProcessRecord()
{
    this.Host.UI.WriteLine("New name is " + this.NewName);
}

Другие советы

ДА.-NewName занимает блок скрипта.Попробуй это:

Function Do-MyRename {
  param([ScriptBlock]$sb)

  dir *.ps1| Rename-Item -NewName $sb
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top