Прочитать на английском

Поделиться через


Глава 4. One-Liners и конвейер

Когда я начал изучать PowerShell, я изначально опирался на графический пользовательский интерфейс (GUI) для задач, которые казалось слишком сложными для простых команд PowerShell. По мере того как я продолжал учиться, я улучшал свои навыки и перешел от простых однострочных программ к созданию скриптов, функций и модулей. Важно помнить, что чувство перегруженности сложными примерами в интернете является нормальным. Никто не становится экспертом по PowerShell; мы все начинаем как новички.

Для тех, кто в основном использует графический интерфейс для административных задач, установите средства управления на административной рабочей станции для удаленного управления серверами. Независимо от того, используется ли на сервере GUI или установка Server Core OS, этот подход является полезным. Это практический способ ознакомиться с удаленным управлением серверами при подготовке к выполнению административных задач с помощью PowerShell.

Как и в предыдущих разделах, попробуйте использовать эти понятия в лабораторной среде.

Короткие шутки

Однострочник PowerShell представляет собой непрерывный конвейер. Это распространенное неправильное представление о том, что команда в одной физической строке является однострочной строкой PowerShell, но это не всегда верно.

Например, рассмотрим следующий пример: команда растягивается на несколько физических строк, но это однострочная команда PowerShell, так как она образует непрерывный конвейер. Для повышения удобочитаемости и ясности рекомендуется разбить длинную однострочную команду на символе pipe, который является естественным местом для разрыва в PowerShell. Это стратегическое использование разрывов линий улучшает удобочитаемость без нарушения потока конвейера.

Get-Service |
    Where-Object CanPauseAndContinue -EQ $true |
    Select-Object -Property *
Name                : LanmanWorkstation
RequiredServices    : {NSI, MRxSmb20, Bowser}
CanPauseAndContinue : True
CanShutdown         : False
CanStop             : True
DisplayName         : Workstation
DependentServices   : {SessionEnv, Netlogon}
MachineName         : .
ServiceName         : LanmanWorkstation
ServicesDependedOn  : {NSI, MRxSmb20, Bowser}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Automatic
Site                :
Container           :

Name                : Netlogon
RequiredServices    : {LanmanWorkstation}
CanPauseAndContinue : True
CanShutdown         : False
CanStop             : True
DisplayName         : Netlogon
DependentServices   : {}
MachineName         : .
ServiceName         : Netlogon
ServicesDependedOn  : {LanmanWorkstation}
ServiceHandle       :
Status              : Running
ServiceType         : Win32ShareProcess
StartType           : Automatic
Site                :
Container           :

Name                : vmicheartbeat
RequiredServices    : {}
CanPauseAndContinue : True
CanShutdown         : False
CanStop             : True
DisplayName         : Hyper-V Heartbeat Service
DependentServices   : {}
MachineName         : .
ServiceName         : vmicheartbeat
ServicesDependedOn  : {}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Manual
Site                :
Container           :

Name                : vmickvpexchange
RequiredServices    : {}
CanPauseAndContinue : True
CanShutdown         : False
CanStop             : True
DisplayName         : Hyper-V Data Exchange Service
DependentServices   : {}
MachineName         : .
ServiceName         : vmickvpexchange
ServicesDependedOn  : {}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Manual
Site                :
Container           :

Name                : vmicrdv
RequiredServices    : {}
CanPauseAndContinue : True
CanShutdown         : False
CanStop             : True
DisplayName         : Hyper-V Remote Desktop Virtualization Service
DependentServices   : {}
MachineName         : .
ServiceName         : vmicrdv
ServicesDependedOn  : {}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Manual
Site                :
Container           :

Name                : vmicshutdown
RequiredServices    : {}
CanPauseAndContinue : True
CanShutdown         : False
CanStop             : True
DisplayName         : Hyper-V Guest Shutdown Service
DependentServices   : {}
MachineName         : .
ServiceName         : vmicshutdown
ServicesDependedOn  : {}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Manual
Site                :
Container           :

Name                : vmicvss
RequiredServices    : {}
CanPauseAndContinue : True
CanShutdown         : False
CanStop             : True
DisplayName         : Hyper-V Volume Shadow Copy Requestor
DependentServices   : {}
MachineName         : .
ServiceName         : vmicvss
ServicesDependedOn  : {}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Manual
Site                :
Container           :

Name                : webthreatdefsvc
RequiredServices    : {RpcSs, wtd}
CanPauseAndContinue : True
CanShutdown         : True
CanStop             : True
DisplayName         : Web Threat Defense Service
DependentServices   : {}
MachineName         : .
ServiceName         : webthreatdefsvc
ServicesDependedOn  : {RpcSs, wtd}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Manual
Site                :
Container           :

Name                : webthreatdefusersvc_644de
RequiredServices    : {}
CanPauseAndContinue : True
CanShutdown         : True
CanStop             : True
DisplayName         : Web Threat Defense User Service_644de
DependentServices   : {}
MachineName         : .
ServiceName         : webthreatdefusersvc_644de
ServicesDependedOn  : {}
ServiceHandle       :
Status              : Running
ServiceType         : 240
StartType           : Automatic
Site                :
Container           :

Name                : Winmgmt
RequiredServices    : {RPCSS}
CanPauseAndContinue : True
CanShutdown         : True
CanStop             : True
DisplayName         : Windows Management Instrumentation
DependentServices   : {}
MachineName         : .
ServiceName         : Winmgmt
ServicesDependedOn  : {RPCSS}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Automatic
Site                :
Container           :

Естественные разрывы строк могут возникать при часто используемых символах, включая запятую (,) и открывающиеся скобки ([), скобки ({), а также скобки ((). Другие, которые не так распространены, включают точку с запятой (;), знак равенства (=), а также открытие одиночных и двойных кавычки (',").

Использование обратного апострофа (`) или символа гравис для продолжения строки является спорным. Лучше всего избежать этого, если это возможно. Использование обратной кавычки после естественного символа разрыва строки является распространенной ошибкой. Эта избыточность не требуется и может загромождать код.

Команды в следующем примере выполняются правильно из консоли PowerShell. Однако попытка запустить их в области консоли интегрированной среды сценариев PowerShell (ISE) приводит к ошибке. В отличие от консоли PowerShell, панель консоли Интегрированной среды скриптов не предполагает автоматически продолжение команды на следующую строку. Чтобы предотвратить эту проблему, нажмите клавиши Shift +Enter в области консоли ISE вместо Enter, когда вам нужно разбить команду на несколько строк. Эта комбинация ключей сигнализирует isE о том, что команда продолжается в следующей строке, предотвращая выполнение, которое приводит к ошибкам.

Get-Service -Name w32time |
    Select-Object -Property *
Name                : w32time
RequiredServices    : {}
CanPauseAndContinue : False
CanShutdown         : True
CanStop             : True
DisplayName         : Windows Time
DependentServices   : {}
MachineName         : .
ServiceName         : w32time
ServicesDependedOn  : {}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess, Win32ShareProcess
StartType           : Manual
Site                :
Container           :

В следующем примере не является однострочным скриптом PowerShell, так как это не один непрерывный конвейер. Вместо этого это две отдельные команды, размещенные в одной строке, разделенные точкой с запятой. Эта точка с запятой указывает конец одной команды и начало другой.

$Service = 'w32time'; Get-Service -Name $Service
Status   Name               DisplayName
------   ----               -----------
Running  w32time            Windows Time

Для многих языков программирования и скриптов требуется точка с запятой в конце каждой строки. Однако в PowerShell точки с запятой в конце строк не нужны и не рекомендуются. Их следует избегать для более чистого и более читаемого кода.

Фильтр слева

В этой главе показано, как фильтровать результаты различных команд.

Рекомендуемой практикой в PowerShell является фильтрация результатов как можно раньше в конвейере. Это предполагает применение фильтров с помощью параметров в начальной команде, обычно в начале конвейера. Обычно этот процесс называется фильтрацией по левому.

Чтобы проиллюстрировать эту концепцию, рассмотрим следующий пример: используйте параметр Name из Get-Service для фильтрации результатов на начальном этапе конвейера, возвращая только сведения о "службе времени Windows". Этот метод демонстрирует эффективное получение данных, обеспечивая возврат только необходимых и соответствующих сведений.

Get-Service -Name w32time
Status   Name               DisplayName
------   ----               -----------
Running  w32time            Windows Time

Обычно вы увидите в Интернете примеры передачи команды PowerShell в командлет Where-Object для фильтрации результатов. Этот метод неэффективн, если более ранняя команда в конвейере имеет параметр для выполнения фильтрации.

Get-Service | Where-Object Name -EQ w32time
Status   Name               DisplayName
------   ----               -----------
Running  W32Time            Windows Time

Первый пример демонстрирует фильтрацию непосредственно в источнике, возвращая результаты специально для службы времени Windows. В отличие от этого, второй пример извлекает все службы, а затем использует другую команду для фильтрации результатов. Это может показаться незначительным в небольших сценариях, но рассмотрим ситуацию, связанную с большим набором данных, например Active Directory. Неэффективно получить сведения для тысяч учетных записей пользователей, чтобы сузить их до небольшого подмножества. Практика фильтрации на ранних этапах — применять фильтры как можно раньше в последовательности команд, даже в, казалось бы, тривиальных случаях. Эта привычка обеспечивает эффективность в более сложных сценариях, где она становится более важной.

Пошаговые действия команд для эффективной фильтрации

Существует заблуждение, что порядок команд в PowerShell не имеет значения, но это ошибочное мнение. Последовательность, в которой вы упорядочиваете команды, особенно при фильтрации, важна. Например, предположим, что вы используете Select-Object для выбора определенных свойств и Where-Object для фильтрации. В этом случае необходимо сначала применить фильтрацию. В случае сбоя необходимые свойства могут быть недоступны в цепочке обработки для фильтрации, что приводит к неэффективным или ошибочным результатам.

В следующем примере не удается получить результаты, так как свойство CanPauseAndContinue отсутствует, когда Select-Object передан в Where-Object. Это связано с тем, что свойство CanPauseAndContinue не было включено в выбор, сделанный Select-Object. Фактически это исключается или отфильтровывается.

Get-Service |
    Select-Object -Property DisplayName, Running, Status |
    Where-Object CanPauseAndContinue

Изменение порядка Select-Object и Where-Object приводит к желаемым результатам.

Get-Service |
    Where-Object CanPauseAndContinue |
    Select-Object -Property DisplayName, Status
DisplayName                                    Status
-----------                                    ------
Workstation                                   Running
Netlogon                                      Running
Hyper-V Heartbeat Service                     Running
Hyper-V Data Exchange Service                 Running
Hyper-V Remote Desktop Virtualization Service Running
Hyper-V Guest Shutdown Service                Running
Hyper-V Volume Shadow Copy Requestor          Running
Web Threat Defense Service                    Running
Web Threat Defense User Service_644de         Running
Windows Management Instrumentation            Running

Конвейер

Как показано во многих примерах в этой книге, вы часто можете использовать выходные данные одной команды в качестве входных данных для другой команды. В главе 3 Get-Member использовалось для определения типа объекта, создаваемого командой.

Глава 3 также показала использование параметра ParameterTypeGet-Command для определения того, какие команды приняли этот тип входных данных. В зависимости от того, насколько подробна помощь по команде, она может включать разделы INPUTS и OUTPUTS.

В разделе INPUTS указано, что можно передать ServiceController или объект String командлету Stop-Service.

help Stop-Service -Full

Следующий результат сокращен, чтобы отобразить релевантную часть инструкции.

...
INPUTS
    System.ServiceProcess.ServiceController
        You can pipe a service object to this cmdlet.

    System.String
        You can pipe a string that contains the name of a service to this
        cmdlet.


OUTPUTS
    None
        By default, this cmdlet returns no output.

    System.ServiceProcess.ServiceController
        When you use the PassThru parameter, this cmdlet returns a
        ServiceController object representing the service.
...

Однако он не указывает, какие параметры принимают этот тип входных данных. Эту информацию можно узнать, проверив различные параметры в полной версии справки о командлете Stop-Service.

help Stop-Service -Full

Снова в результатах ниже отображается только соответствующая справка. Обратите внимание, что параметр DisplayName не принимает входные данные конвейера. Параметр InputObject принимает данные из конвейера по значению для объектов ServiceController. Параметр Name принимает входные данные конвейера по значению для объектов String и входных данных конвейера по имени свойства.

...
-DisplayName <System.String[]>
    Specifies the display names of the services to stop. Wildcard
    characters are permitted.

    Required?                    true
    Position?                    named
    Default value                None
    Accept pipeline input?       False
    Accept wildcard characters?  true

-InputObject <System.ServiceProcess.ServiceController[]>
    Specifies ServiceController objects that represent the services to
    stop. 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 <System.String[]>
    Specifies the service names of the services to stop. Wildcard
    characters are permitted.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByPropertyName, ByValue)
    Accept wildcard characters?  true
...

При обработке входных данных конвейера, если параметр принимает данные как по имени свойства, так и по значению, сначала отдается предпочтение привязке по значению. Если этот метод терпит неудачу, он пытается обработать входные данные конвейера , используя имя свойства. Однако термин в значении может вводить в заблуждение. Более точное описание по типу— это .

Например, если вы отправляете выходные данные команды, создающей объект ServiceController в Stop-Service, эти выходные данные привязаны к параметру InputObject. Если команда, работающая через пайп, создает объект String, она связывает выходные данные с параметром Name. Если вы отправляете выходные данные из команды, которая не создает ServiceController или объект String, но включает свойство с именем Name, Stop-Service привязывает значение свойства Name к его параметру Name.

Определите, какой тип выходных данных создаёт команда Get-Service.

Get-Service -Name w32time | Get-Member

Get-Service создает тип объекта ServiceController.

   TypeName: System.ServiceProcess.ServiceController

Как показано в справке для командлета Stop-Service, параметр InputObject принимает объекты ServiceController через конвейер по значению. Это означает, что при передаче выходных данных командлета Get-Service в Stop-Service, объекты ServiceController, созданные Get-Service, привязываются к параметру InputObject командлета Stop-Service.

Get-Service -Name w32time | Stop-Service

Теперь попробуйте использовать строковые входные данные. Соедините w32time с Get-Member, чтобы убедиться, что это строка.

'w32time' | Get-Member
   TypeName: System.String

В документации по PowerShell показано, что при передаче строки через конвейер в Stop-Service, эта строка привязывается к параметру Nameпо значению. Проведите практический тест, чтобы увидеть это в действии: перенаправьте символьную строку w32time на Stop-Service. В этом примере показано, как Stop-Service обрабатывает строку w32time в качестве имени службы для остановки. Выполните следующую команду, чтобы наблюдать за этой привязкой и выполнением команд в действии.

Обратите внимание, что w32time заключён в одинарные кавычки. В PowerShell рекомендуется использовать одинарные кавычки для статических строк, резервируя двойные кавычки для ситуаций, когда строка содержит переменные, требующие расширения. Одинарные кавычки задают PowerShell обрабатывать содержимое буквально, без разбора переменных. Этот подход не только гарантирует точность в том, как скрипт интерпретирует строку, но и повышает производительность, так как PowerShell тратит меньше усилий по обработке строк в отдельных кавычках.

'w32time' | Stop-Service

Создайте пользовательский объект для тестирования входных данных конвейера по имени свойства для параметра NameStop-Service.

$customObject = [pscustomobject]@{
    Name = 'w32time'
}

Содержимое переменной CustomObject является объектом типа PSCustomObject и содержит свойство с именем Name.

$customObject | Get-Member
   TypeName: System.Management.Automation.PSCustomObject

Name        MemberType   Definition
----        ----------   ----------
Equals      Method       bool Equals(System.Object obj)
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
ToString    Method       string ToString()
Name        NoteProperty string Name=w32time

При работе с переменными в PowerShell, например $customObject в этом примере, важно использовать двойные кавычки, если необходимо заключить переменную в кавычки. Двойные кавычки позволяют расширить переменную. PowerShell оценивает переменную и использует его значение. Например, если заключить $customObject в двойные кавычки и перенаправить его в Get-Member, PowerShell обработает значение $customObject. Напротив, использование одинарных кавычек приведет к передаче строкового литерала $customObject и Get-Member, а не значения переменной. Это различие важно для сценариев, в которых необходимо оценить значение переменных.

При отправке содержимого переменной $customObject в командлет Stop-Service привязка к параметру Name выполняется по имени свойства , а не по значению . Это связано с тем, что $customObject — это объект, содержащий свойство с именем Имя. В этом сценарии PowerShell определяет свойство Name в $customObject и использует его значение для параметра Name для Stop-Service.

Создайте другой пользовательский объект с помощью другого имени свойства, например Service.

$customObject = [pscustomobject]@{
    Service = 'w32time'
}

Ошибка возникает при попытке остановить службу w32time, перенаправляя $customObject в Stop-Service. Привязка конвейера вызывает ошибку, так как $customObject не создает объект ServiceController или String и не содержит свойство Name.

$customObject | Stop-Service
Stop-Service : Cannot find any service with service name
'@{Service=w32time}'.
At line:1 char:17
+ $customObject | Stop-Service
+                 ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (@{Service=w32time}:String) [
   Stop-Service], ServiceCommandException
    + FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShe
   ll.Commands.StopServiceCommand

Если имена выходных свойств одной команды не соответствуют требованиям к входным данным конвейера другой команды, можно использовать Select-Object для переименования имен свойств, чтобы они правильно выстроились.

В следующем примере используйте Select-Object для переименования свойства Service в свойство с именем Name.

На первый взгляд синтаксис этого примера может показаться сложным. Однако важно понимать, что для изучения синтаксиса требуется больше, чем копирование и вставка кода. Вместо этого потребуется время, чтобы ввести код вручную. Эта практическая практика помогает запоминать синтаксис, и он становится более интуитивно понятным при повторяющихся усилиях. Использование нескольких мониторов или разбиения экрана также может помочь в процессе обучения. Отображение примера кода на одном экране при активном вводе и эксперименте с ним на другом. Эта настройка облегчает следование за материалом и улучшает ваше понимание и запоминание синтаксиса.

$customObject |
    Select-Object -Property @{Name='Name';Expression={$_.Service}} |
    Stop-Service

Существуют случаи, в которых может потребоваться использовать параметр, который не принимает входные данные конвейера. В таких случаях вы по-прежнему можете использовать выходные данные одной команды в качестве входных данных для другого. Во-первых, захват и сохранение отображаемых имен нескольких определенных служб Windows в текстовый файл. Этот шаг позволяет использовать сохраненные данные в качестве входных данных для другой команды.

'Background Intelligent Transfer Service', 'Windows Time' |
    Out-File -FilePath $env:TEMP\services.txt

Скобки можно использовать для передачи выходных данных одной команды в качестве входных данных для параметра другой команде.

Stop-Service -DisplayName (Get-Content -Path $env:TEMP\services.txt)

Эта концепция похожа на порядок операций в Алгебре. Так же, как математические операции в скобках вычисляются сначала, команда, заключенная в скобки, выполняется перед внешней командой.

PowerShellGet

PowerShellGet, модуль, включенный в PowerShell версии 5.0 и выше, предоставляет команды для обнаружения, установки, обновления и публикации модулей PowerShell и других элементов в репозитории NuGet. Для тех, кто использует PowerShell версии 3.0 и выше, PowerShellGet также доступен как отдельная загрузка.

Галерея PowerShell — это веб-репозиторий, размещённый в корпорации Майкрософт, разработанный как централизованная платформа для обмена модулями PowerShell, скриптами и другими ресурсами. Хотя корпорация Майкрософт размещает коллекцию PowerShell, сообщество PowerShell вносит большую часть доступных модулей и сценариев. Учитывая источник этих модулей и скриптов, обратите внимание, прежде чем интегрировать любой код из коллекции PowerShell в среду. Просмотрите и проверьте скачиваемые файлы из коллекции PowerShell в изолированной тестовой среде. Этот процесс гарантирует, что код является безопасным и надежным, работает должным образом и защищает вашу среду от потенциальных проблем или уязвимостей, возникающих из невидимого кода.

Многие организации предпочитают устанавливать собственный внутренний частный репозиторий NuGet. Этот репозиторий служит двойной целью. Во-первых, он выступает в качестве безопасного расположения для хранения модулей, разработанных в собственной среде, предназначенных исключительно для внутреннего использования. Во-вторых, он предоставляет проверенную коллекцию модулей, поступающих из внешних источников, включая общедоступные репозитории. Компании обычно проводят тщательную проверку перед добавлением этих внешних модулей в внутренний репозиторий. Этот процесс важен для обеспечения того, чтобы модули были свободны от вредоносного содержимого и соответствуют стандартам безопасности и эксплуатации компании.

Используйте командлет Find-Module, который является частью модуля PowerShellGet, чтобы найти модуль в галерее PowerShell, написанный мной и называющийся MrToolkit.

Find-Module -Name MrToolkit
NuGet provider is required to continue
PowerShellGet requires NuGet provider version '2.8.5.201' or newer to
interact with NuGet-based repositories. The NuGet provider must be available
 in 'C:\Program Files\PackageManagement\ProviderAssemblies' or
'C:\Users\mikefrobbins\AppData\Local\PackageManagement\ProviderAssemblies'.
You can also install the NuGet provider by running 'Install-PackageProvider
-Name NuGet -MinimumVersion 2.8.5.201 -Force'. Do you want PowerShellGet to
install and import the NuGet provider now?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"):

Version    Name                      Repository        Description
-------    ----                      ----------        -----------
1.3        MrToolkit                 PSGallery         Misc PowerShell Tools

При первом использовании одной из команд из модуля PowerShellGet появится запрос на установку поставщика NuGet.

Чтобы установить модуль MrToolkit, передайте предыдущую команду в Install-Module.

Find-Module -Name MrToolkit | Install-Module -Scope CurrentUser
Untrusted repository
You are installing the modules from an untrusted repository. If you trust
this repository, change its InstallationPolicy value by running the
Set-PSRepository cmdlet. Are you sure you want to install the modules from
'https://www.powershellgallery.com/api/v2'?
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help
(default is "N"):y

Так как коллекция PowerShell является ненадежным репозиторием, вам будет предложено утвердить установку модуля.

Поиск входных данных конвейера упрощённым способом

Модуль MrToolkit включает функцию с именем Get-MrPipelineInput. Этот командлет предназначен для предоставления пользователям удобного метода для идентификации параметров команд, способных принимать входные данные из конвейера. В частности, он показывает три ключевых аспекта:

  • Какие параметры команды могут принимать входные данные из конвейера
  • Тип объекта, который принимает каждый параметр
  • Принимают ли они входные данные конвейера по значению или по имени свойства

Эта возможность значительно упрощает процесс понимания и использования возможностей конвейера команд PowerShell.

Сведения, полученные ранее путем анализа справочной документации, могут быть определены этой функцией.

Get-MrPipelineInput -Name Stop-Service | Format-List
ParameterName                   : InputObject
ParameterType                   : System.ServiceProcess.ServiceController[]
ValueFromPipeline               : True
ValueFromPipelineByPropertyName : False

ParameterName                   : Name
ParameterType                   : System.String[]
ValueFromPipeline               : True
ValueFromPipelineByPropertyName : True

Сводка

В этой главе вы узнали о тонкостях однострочных команд PowerShell. Вы также узнали, что количество физических строк команды не имеет значения для ее классификации как однострочной команды PowerShell. Кроме того, вы узнали о ключевых понятиях, таких как фильтрация слева, конвейер и PowerShellGet.

Обзор

  1. Что такое однострочник PowerShell?
  2. Каковы некоторые символы, в которых могут возникать естественные разрывы строк в PowerShell?
  3. Почему следует фильтровать влево?
  4. Каковы два способа, которым команда PowerShell может принимать входные данные конвейера?
  5. Почему вы не должны доверять командам, найденным в галерее PowerShell?

Ссылки

Дальнейшие действия

В следующей главе вы узнаете о форматировании, псевдонимах, поставщиках и операторах сравнения.