Сведения о конвейерах
Краткое описание
Объединение команд в конвейеры в PowerShell
Подробное описание
Конвейер — это ряд команд, соединенных операторами конвейера (|
) (ASCII 124). Каждый оператор конвейера отправляет результаты предыдущей команды в следующую команду.
Выходные данные первой команды можно отправить для обработки в качестве входных данных для второй команды. И эти выходные данные можно отправить в еще одну команду. Результатом является сложная цепочка команд или конвейер, состоящий из ряда простых команд.
Например,
Command-1 | Command-2 | Command-3
В этом примере генерируемые Command-1
объекты отправляются в Command-2
.
Command-2
обрабатывает объекты и отправляет их в Command-3
. Command-3
обрабатывает объекты и отправляет их по конвейеру. Так как в конвейере больше нет команд, результаты отображаются в консоли.
В конвейере команды обрабатываются по порядку слева направо. Обработка обрабатывается как одна операция, а выходные данные отображаются по мере ее создания.
Вот простой пример. Следующая команда получает процесс Блокнота, а затем останавливает его.
Например,
Get-Process notepad | Stop-Process
Первая команда использует Get-Process
командлет для получения объекта, представляющего процесс Блокнота. Он использует оператор конвейера (|
) для отправки объекта процесса в Stop-Process
командлет , который останавливает процесс Блокнота. Обратите внимание, что команда Stop-Process
не имеет параметра Name или ID для указания процесса, так как указанный процесс отправляется через конвейер.
Этот пример конвейера получает текстовые файлы в текущем каталоге, выбирает только файлы длиной более 10 000 байт, сортирует их по длине и отображает имя и длину каждого файла в таблице.
Get-ChildItem -Path *.txt |
Where-Object {$_.length -gt 10000} |
Sort-Object -Property length |
Format-Table -Property name, length
Этот конвейер состоит из четырех команд в указанном порядке. На следующем рисунке показаны выходные данные каждой команды, передаваемые в следующую команду в конвейере.
Get-ChildItem -Path *.txt
| (FileInfo objects for *.txt)
V
Where-Object {$_.length -gt 10000}
| (FileInfo objects for *.txt)
| ( Length > 10000 )
V
Sort-Object -Property Length
| (FileInfo objects for *.txt)
| ( Length > 10000 )
| ( Sorted by length )
V
Format-Table -Property name, length
| (FileInfo objects for *.txt)
| ( Length > 10000 )
| ( Sorted by length )
| ( Formatted in a table )
V
Name Length
---- ------
tmp1.txt 82920
tmp2.txt 114000
tmp3.txt 114000
Использование конвейеров
Большинство командлетов PowerShell предназначены для поддержки конвейеров. В большинстве случаев результаты командлета Getможно передать в другой командлет того же существительного.
Например, можно передать выходные данные командлета в Get-Service
Start-Service
командлеты или Stop-Service
.
В этом примере конвейера запускается служба WMI на компьютере:
Get-Service wmi | Start-Service
В другом примере можно передать выходные данные Get-Item
поставщика реестра New-ItemProperty
PowerShell или Get-ChildItem
в командлет . В этом примере в раздел реестра MyCompany добавляется новая запись реестра NoOfEmployees со значением 8124.
Get-Item -Path HKLM:\Software\MyCompany |
New-ItemProperty -Name NoOfEmployees -Value 8124
Многие служебные командлеты, такие как Get-Member
, Where-Object
, Sort-Object
, Group-Object
и Measure-Object
, используются почти исключительно в конвейерах. В эти командлеты можно передать объект любого типа. В этом примере показано, как отсортировать все процессы на компьютере по количеству открытых дескрипторов в каждом процессе.
Get-Process | Sort-Object -Property handles
Объекты можно передавать по конвейеру в командлеты форматирования, экспорта и вывода, такие как Format-List
, Format-Table
, Export-Clixml
, Export-CSV
и Out-File
.
В этом примере показано, как использовать Format-List
командлет для отображения списка свойств объекта процесса.
Get-Process winlogon | Format-List -Property *
Немного потренируясь, вы обнаружите, что объединение простых команд в конвейеры экономит время и ввод текста, а также делает скрипты более эффективными.
Принцип работы конвейеров
В этом разделе объясняется, как входные объекты привязываются к параметрам командлета и обрабатываются во время выполнения конвейера.
Принимает входные данные конвейера
Для поддержки конвейерной конвейерной передачи принимающий командлет должен иметь параметр, который принимает входные данные конвейера. Get-Help
Используйте команду с параметрами Full или Parameter, чтобы определить, какие параметры командлета принимают входные данные конвейера.
Например, чтобы определить, какие из параметров командлета Start-Service
принимают входные данные конвейера, введите следующее:
Get-Help Start-Service -Full
или
Get-Help Start-Service -Parameter *
В справке по командлету Start-Service
показано, что только параметры InputObject и Name принимают входные данные конвейера.
-InputObject <ServiceController[]>
Specifies ServiceController objects representing the services to be started.
Enter a variable that contains the objects, or type a command or expression
that gets the objects.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByValue)
Accept wildcard characters? false
-Name <String[]>
Specifies the service names for the service to be started.
The parameter name is optional. You can use Name or its alias, ServiceName,
or you can omit the parameter name.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? false
При отправке объектов через конвейер в PowerShell пытается Start-Service
связать объекты с параметрами InputObject и Name .
Методы приема входных данных конвейера
Параметры командлетов могут принимать входные данные конвейера одним из двух разных способов:
ByValue: параметр принимает значения, соответствующие ожидаемому типу .NET или которые можно преобразовать в этот тип.
Например, параметр Name объекта принимает входные данные конвейера
Start-Service
по значению. Он может принимать строковые объекты или объекты, которые можно преобразовать в строки.ByPropertyName: параметр принимает входные данные, только если входной объект имеет свойство с тем же именем, что и параметр.
Например, параметр
Start-Service
Name объекта может принимать объекты со свойством Name . Чтобы получить список свойств объекта, передайте его вGet-Member
.
Некоторые параметры могут принимать объекты как по значению, так и по имени свойства, что упрощает получение входных данных из конвейера.
Привязка параметра
Когда объекты передаются из одной команды в другую, PowerShell пытается связать полученные объекты с параметром принимающего командлета.
Компонент привязки параметров PowerShell связывает входные объекты с параметрами командлета в соответствии со следующими критериями:
- Параметр должен принимать входные данные из конвейера.
- Параметр должен принимать тип отправляемого объекта или тип, который можно преобразовать в ожидаемый тип.
- Параметр не использовался в команде .
Например, Start-Service
командлет имеет много параметров, но только два из них, Name и InputObject , принимают входные данные конвейера. Параметр Name принимает строки, а параметр InputObject принимает объекты службы. Таким образом, строки, объекты службы и объекты можно передавать по конвейеру со свойствами, которые можно преобразовать в строковые или служебные объекты.
PowerShell максимально эффективно управляет привязкой параметров. Вы не можете предложить или принудительно привязать PowerShell к определенному параметру. Команда завершается ошибкой, если PowerShell не может привязать объекты, которые передаются по конвейеру.
Дополнительные сведения об устранении ошибок привязки см. в разделе Исследование ошибок конвейера далее в этой статье.
Разовая обработка
Передача объектов в команду во многом похожа на использование параметра команды для отправки объектов. Рассмотрим пример конвейера. В этом примере мы используем конвейер для отображения таблицы объектов службы.
Get-Service | Format-Table -Property Name, DependentServices
Функционально это похоже на использование параметра InputObject для Format-Table
отправки коллекции объектов.
Например, можно сохранить коллекцию служб в переменной, передаваемой с помощью параметра InputObject .
$services = Get-Service
Format-Table -InputObject $services -Property Name, DependentServices
Или мы можем внедрить команду в параметр InputObject .
Format-Table -InputObject (Get-Service) -Property Name, DependentServices
Тем не менее, есть важное различие. Когда вы передаете несколько объектов в команду, PowerShell отправляет объекты команде по одному за раз. При использовании параметра команды объекты отправляются в виде одного объекта массива. Это незначительное различие имеет значительные последствия.
При выполнении конвейера PowerShell автоматически перечисляет любой тип, реализующий IEnumerable
интерфейс , и отправляет члены через конвейер по одному за раз. Исключением является [hashtable]
, для которого требуется GetEnumerator()
вызов метода .
В следующих примерах массив и хэш-сводка передаются в Measure-Object
командлет для подсчета количества объектов, полученных из конвейера. Массив содержит несколько элементов, а хэш-диаграмма содержит несколько пар "ключ-значение". По одному перечисляется только массив.
@(1,2,3) | Measure-Object
Count : 3
Average :
Sum :
Maximum :
Minimum :
Property :
@{"One"=1;"Two"=2} | Measure-Object
Count : 1
Average :
Sum :
Maximum :
Minimum :
Property :
Аналогичным образом, если передать несколько объектов процесса из командлета Get-Process
в Get-Member
командлет, PowerShell отправляет каждый объект процесса по одному в Get-Member
. Get-Member
отображает класс (тип) .NET объектов процесса, а также их свойства и методы.
Get-Process | Get-Member
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
NPM AliasProperty NPM = NonpagedSystemMemorySize
...
Примечание
Get-Member
устраняет дубликаты, поэтому, если все объекты относятся к одному типу, отображается только один тип объекта.
Однако если вы используете параметр Get-Member
InputObject для , то Get-Member
получает массив объектов System.Diagnostics.Process как единое целое. Он отображает свойства массива объектов . (Обратите внимание на символ массива ([]
) после имени типа System.Object .)
Например,
Get-Member -InputObject (Get-Process)
TypeName: System.Object[]
Name MemberType Definition
---- ---------- ----------
Count AliasProperty Count = Length
Address Method System.Object& Address(Int32 )
Clone Method System.Object Clone()
...
Этот результат может быть не таким, как вы намеревались. Но после того, как вы поймете это, вы можете использовать его. Например, все объекты массива имеют свойство Count . Его можно использовать для подсчета количества процессов, запущенных на компьютере.
Например,
(Get-Process).count
Важно помнить, что объекты, отправленные по конвейеру, доставляются по одному.
Исследование ошибок конвейера
Если PowerShell не удается связать переданные объекты с параметром принимающего командлета, команда завершается ошибкой.
В следующем примере мы пытаемся переместить запись реестра из одного раздела реестра в другой. Командлет Get-Item
получает целевой путь, который затем передается в Move-ItemProperty
командлет. Команда Move-ItemProperty
задает текущий путь и имя перемещаемой записи реестра.
Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
Команда завершается ошибкой, и PowerShell отображает следующее сообщение об ошибке:
Move-ItemProperty : The input object can't be bound to any parameters for
the command either because the command doesn't take pipeline input or the
input and its properties do not match any of the parameters that take
pipeline input.
At line:1 char:23
+ $a | Move-ItemProperty <<<< -Path HKLM:\Software\MyCompany\design -Name p
Для исследования используйте командлет для Trace-Command
трассировки компонента привязки параметров PowerShell. В следующем примере выполняется трассировка привязки параметров во время выполнения конвейера. Параметр PSHost отображает результаты трассировки в консоли, а параметр FilePath отправляет результаты трассировки в файл для последующего debug.txt
использования.
Trace-Command -Name ParameterBinding -PSHost -FilePath debug.txt -Expression {
Get-Item -Path HKLM:\Software\MyCompany\sales |
Move-ItemProperty -Path HKLM:\Software\MyCompany\design -Name product
}
Результаты трассировки являются длинными, но они показывают, что значения привязаны к командлету Get-Item
, а затем именованные значения привязываются к командлету Move-ItemProperty
.
...
BIND NAMED cmd line args [`Move-ItemProperty`]
BIND arg [HKLM:\Software\MyCompany\design] to parameter [Path]
...
BIND arg [product] to parameter [Name]
...
BIND POSITIONAL cmd line args [`Move-ItemProperty`]
...
Наконец, это показывает, что попытка привязки пути к параметру Destination объекта завершилась сбоем Move-ItemProperty
.
...
BIND PIPELINE object to parameters: [`Move-ItemProperty`]
PIPELINE object TYPE = [Microsoft.Win32.RegistryKey]
RESTORING pipeline parameter's original values
Parameter [Destination] PIPELINE INPUT ValueFromPipelineByPropertyName NO
COERCION
Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName NO
COERCION
...
Get-Help
Используйте командлет для просмотра атрибутов параметра Destination.
Get-Help Move-ItemProperty -Parameter Destination
-Destination <String>
Specifies the path to the destination location.
Required? true
Position? 1
Default value None
Accept pipeline input? True (ByPropertyName)
Accept wildcard characters? false
Результаты показывают, что назначение принимает входные данные конвейера только "по имени свойства". Таким образом, объект, который передается по конвейеру, должен иметь свойство с именем Destination.
Используйте Get-Member
для просмотра свойств объекта , поступающих из Get-Item
.
Get-Item -Path HKLM:\Software\MyCompany\sales | Get-Member
В выходных данных показано, что элемент является объектом Microsoft.Win32.RegistryKey без свойства Destination . Это объясняет, почему команда завершилась сбоем.
Параметр Path принимает входные данные конвейера по имени или значению.
Get-Help Move-ItemProperty -Parameter Path
-Path <String[]>
Specifies the path to the current location of the property. Wildcard
characters are permitted.
Required? true
Position? 0
Default value None
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? true
Чтобы исправить команду, необходимо указать назначение в командлете Move-ItemProperty
и использовать Get-Item
для получения пути к элементу, который требуется переместить.
Например,
Get-Item -Path HKLM:\Software\MyCompany\design |
Move-ItemProperty -Destination HKLM:\Software\MyCompany\sales -Name product
Встроенное продолжение строки
Как уже говорился, конвейер — это ряд команд, соединенных операторами конвейера (|
), которые обычно записываются в одной строке. Однако для удобочитаемости PowerShell позволяет разделить конвейер на несколько строк.
Если оператор конвейера является последним маркером в строке, средство синтаксического анализа PowerShell присоединяет следующую строку к текущей команде, чтобы продолжить построение конвейера.
Например, следующий однострочный конвейер:
Command-1 | Command-2 | Command-3
можно написать следующим образом:
Command-1 |
Command-2 |
Command-3
Пробелы в последующих строках не являются значительными. Отступ повышает удобочитаемость.