Learning and Sharing
  • Home
  • Blog
  • Linux
  • macOS
  • Virtualization
    • VMware
    • VirtualBox
  • Windows
    • Windows 11
    • Windows 10
    • Windows Server
  • Series
    • Symantec
    • Intune
    • Microsoft Azure
    • Powershell
    • VirtualBox
    • VMware
    • PowerShell Learning
    • Microsoft Graph
  • More
    • Auto Installation
    • AEC Installation
  • Contact
No Result
View All Result
  • Home
  • Blog
  • Linux
  • macOS
  • Virtualization
    • VMware
    • VirtualBox
  • Windows
    • Windows 11
    • Windows 10
    • Windows Server
  • Series
    • Symantec
    • Intune
    • Microsoft Azure
    • Powershell
    • VirtualBox
    • VMware
    • PowerShell Learning
    • Microsoft Graph
  • More
    • Auto Installation
    • AEC Installation
  • Contact
No Result
View All Result
No Result
View All Result

#16 PowerShell Learning: One-liners and the Pipeline

August 14, 2023
in Blog, PowerShell Learning
0
ADVERTISEMENT

Table of Contents

When I first started learning PowerShell, if I couldn’t accomplish a task with a PowerShell one-liner, I went back to the GUI. Over time, I built my skills up to writing scripts, functions, and modules. Don’t allow yourself to become overwhelmed by some of the more advanced examples you may see on the internet. No one is a natural expert with PowerShell. We were all beginners at one time.

I have a bit of advice to offer those of you who are still using the GUI for administration: install the management tools on your admin workstation and manage your servers remotely. This way it won’t matter if the server is running a GUI or Server Core installation of the operating system. It’s going to help prepare you for managing servers remotely with PowerShell.

One-Liners

A PowerShell one-liner is one continuous pipeline and not necessarily a command that’s on one physical line. Not all commands that are on one physical line are one-liners.

Even though the following command is on multiple physical lines, it’s a PowerShell one-liner because it’s one continuous pipeline. It could be written on one physical line, but I’ve chosen to line break at the pipe symbol. The pipe symbol is one of the characters where a natural line break is allowed in PowerShell.

Get-Service |
  Where-Object CanPauseAndContinue -eq $true |
    Select-Object -Property *

Natural line breaks can occur at commonly used characters including comma (,) and opening brackets ([), braces ({), and parenthesis ((). Others that aren’t so common include the semicolon (;), equals sign (=), and both opening single and double quotes (',").

PS C:\> Get-Service |
>>   Where-Object CanPauseAndContinue -eq $true |
>>     Select-Object -Property *

Name                : dptftcs
RequiredServices    : {}
CanPauseAndContinue : True
CanShutdown         : False
CanStop             : True
DisplayName         : Intel(R) Dynamic Tuning Technology Telemetry Service
DependentServices   : {}
MachineName         : .
ServiceName         : dptftcs
ServicesDependedOn  : {}
ServiceHandle       : SafeServiceHandle
Status              : Running
ServiceType         : Win32OwnProcess
StartType           : Automatic
Site                :
Container           :
...

This next example isn’t a PowerShell one-liner because it’s not one continuous pipeline. It’s two separate commands on one line, separated by a semicolon.

PS C:\> $Service = 'w32time'; Get-Service -Name $Service

Status   Name               DisplayName
------   ----               -----------
Stopped  w32time            Windows Time

Many programming and scripting languages require a semicolon at the end of each line. While they can be used that way in PowerShell, it’s not recommended because they’re not needed.

Filtering Left

The results of the commands shown in this chapter have been filtered down to a subset. For example, Get-Service was used with the Name parameter to filter the list of services that were returned to only the Windows Time service.

In the pipeline, you always want to filter the results down to what you’re looking for as early as possible. This is accomplished using parameters on the first command or, the one to the far left. This is sometimes called filtering left.

The following example uses the Name parameter of Get-Service to immediately filter the results to the Windows Time service only.

PS C:\> Get-Service -Name w32time

Status   Name               DisplayName
------   ----               -----------
Stopped  w32time            Windows Time

It’s not uncommon to see examples where the command is piped to Where-Object to perform the filtering.

PS C:\> Get-Service | Where-Object Name -eq w32time

Status   Name               DisplayName
------   ----               -----------
Stopped  W32Time            Windows Time

The first example filters at the source and only returns the results for the Windows Time service. The second example returns all the services then pipes them to another command to perform the filtering.

While this may not seem like a big deal in this example, imagine if you were querying a list of Active Directory users. Do you really want to return the information for many thousands of user accounts from Active Directory only to pipe them to another command that filters them down to a tiny subset? My recommendation is to always filter left even when it doesn’t seem to matter. You’ll be so use to it that you’ll automatically filter left when it really does matter.

The order that the commands are specified in does indeed matter when performing filtering. For example, consider the scenario where you are using Select-Object to select only a few properties and Where-Object to filter on properties that won’t be in the selection. In that scenario, the filtering must occur first, otherwise the property won’t exist in the pipeline when try to perform the filtering.

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

The command in the previous example doesn’t return any results because the CanStopAndContinue property doesn’t exist when the results of Select-Object are piped to Where-Object. That particular property wasn’t “selected”. In essence, it was filtered out. Reversing the order of Select-Object and Where-Object produces the desired results.

Get-Service |
Where-Object CanPauseAndContinue |
Select-Object -Property DisplayName, Status
DisplayName                                           Status
-----------                                           ------
Intel(R) Dynamic Tuning Technology Telemetry Service Running
Intel(R) Graphics Command Center Service             Running
Intel(R) Innovation Platform Framework Service       Running
Workstation                                          Running
Lenovo Smart Standby                                 Running
Secondary Logon                                      Running
Windows Image Acquisition (WIA)                      Running
Web Threat Defense Service                           Running
Web Threat Defense User Service_79cbb                Running
Windows Management Instrumentation                   Running

The Pipeline

Depending on how thorough a commands help is, it may include an INPUTS and OUTPUTS section.

help Stop-Service -Full

Only the relevant section of the help is shown in the previous results. As you can see, the INPUTS section states that a ServiceController or a String object can be piped to the Stop-Service cmdlet. It doesn’t tell you which parameters accept that type of input. One of the easiest ways to determine that information is to look through the different parameters in the full version of the help for the Stop-Service cmdlet.

...
INPUTS
    System.ServiceProcess.ServiceController, System.String
        You can pipe a service object or a string that contains the name of a service
        to this cmdlet.

OUTPUTS
    None, System.ServiceProcess.ServiceController
        This cmdlet generates a System.ServiceProcess.ServiceController object that
        represents the service, if you use the PassThru parameter. Otherwise, this
        cmdlet does not generate any output.
...

Once again, I’ve only shown the relevant portion of the help in the previous set of results. Notice that the DisplayName parameter doesn’t accept pipeline input, the InputObject parameter accepts pipeline input by value for ServiceController objects, and the Name parameter accepts pipeline input by value for string objects. It also accepts pipeline input by property name.

...
-DisplayName <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?  false

-InputObject <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 <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?  false
...

When a parameter accepts pipeline input by both property name and by value, it always tries by value first. If by value fails, then it tries by property name. By value is a little misleading. I prefer to call it by type. This means if you pipe the results of a command that produces a ServiceController object type to Stop-Service, it binds that input to the InputObject parameter. But if you pipe the results of a command that produces String output to Stop-Service, it binds it to the Name parameter. If you pipe the results of a command that doesn’t produce a ServiceController or String object to Stop-Service, but it does produce output containing a property called Name, then it binds the Name property from the output to the Name parameter of Stop-Service.

Determine what type of output the Get-Service command produces.

PS C:\> Get-Service -Name w32time | Get-Member

   TypeName: System.ServiceProcess.ServiceController

Name                      MemberType    Definition
----                      ----------    ----------
Name                      AliasProperty Name = ServiceName
RequiredServices          AliasProperty RequiredServices = ServicesDependedOn

Get-Service produces a ServiceController object type.

As you previously saw in the help, the InputObject parameter of Stop-Service accepts ServiceController objects via the pipeline by value (by type). This means that when the results of the Get-Service cmdlet are piped to Stop-Service, they bind to the InputObject parameter of Stop-Service.

Get-Service -Name w32time | Stop-Service

Now to try string input. Pipe w32time to Get-Member just to confirm that it’s a string.

PS C:\> 'w32time' | Get-Member

   TypeName: System.String

Name             MemberType            Definition
----             ----------            ----------

As previously shown in the help, piping a string to Stop-Service binds it by value to the Name parameter of Stop-Service. Test this by piping w32time to Stop-Service.

'w32time' | Stop-Service

Notice that in the previous example, I used single quotes around the string w32time. In PowerShell, you should always use single quotes instead of double quotes unless the contents of the quoted string contains a variable that needs to be expanded to its actual value. By using single quotes, PowerShell doesn’t have to parse the contents contained within the quotes so your code runs a little faster.

Create a custom object to test pipeline input by property name for the Name parameter of Stop-Service.

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

The contents of the CustomObject variable is a PSCustomObject object type and it contains a property named Name.

PS C:\> $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

Finding pipeline input the easy way

The MrToolkit module contains a function named Get-MrPipelineInput. This cmdlet can be used to easily determine which parameters of a command accept pipeline input, what type of object they accept, and if they accept pipeline input by value or by property name.

Find-Module -Name MrToolkit | Install-Module
PS C:\> Get-MrPipelineInput -Name Stop-Service

ParameterName ParameterType                             ValueFromPipeline ValueFromPipelineByPropertyName
------------- -------------                             ----------------- -------------------------------
InputObject   System.ServiceProcess.ServiceController[]              True                           False
Name          System.String[]                                        True                            True
5/5 - (1 vote)
Previous Post

#15 PowerShell Learning: PowerShell Functions

Next Post

#17 PowerShell Learning: Everything about PSCustomObject

Related Posts

Running Hyper-V and VMware Workstation on The Same Machine

August 15, 2024

How to Uninstall All Autodesk Products At Once Silently

July 29, 2024
Ftr5

How to Uninstall the Autodesk Genuine Service on Windows

July 29, 2024
Ftr19

How to Fix Windows Cannot Read the ProductKey From the Unattend Answer File in VirtualBox

July 26, 2024
Ftr25

How to Update Windows Terminal in Windows 10/11

July 26, 2024

How to Disable The Beep Sound in WSL Terminal on Windows

July 26, 2024

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • How To Turn On uBlock Origin Extension in Chrome (2025)
  • Images Hidden Due To Mature Content Settings In CivitAI
  • Azure OpenAI vs Azure AI Hub, How to Choose the Right One for Your Needs

Categories

Stay in Touch

Discord Server

Join the Discord server with the site members for all questions and discussions.

Telegram Community

Jump in Telegram server. Ask questions and discuss everything with the site members.

Youtube Channel

Watch more videos, learning and sharing with Leo ❤❤❤. Sharing to be better.

Newsletter

Join the movement and receive our weekly Tech related newsletter. It’s Free.

General

Microsoft Windows

Microsoft Office

VMware

VirtualBox

Technology

PowerShell

Microsoft 365

Microsoft Teams

Email Servers

Copyright 2025 © All rights Reserved. Design by Leo with ❤

No Result
View All Result
  • Home
  • Linux
  • Intune
  • macOS
  • VMware
  • VirtualBox
  • Powershell
  • Windows 10
  • Windows 11
  • Microsoft 365
  • Microsoft Azure
  • Microsoft Office
  • Active Directory

No Result
View All Result
  • Home
  • Linux
  • Intune
  • macOS
  • VMware
  • VirtualBox
  • Powershell
  • Windows 10
  • Windows 11
  • Microsoft 365
  • Microsoft Azure
  • Microsoft Office
  • Active Directory