After the sixth part PowerShell for Beginners (Part 6): PowerShell Profiles and the ISE, we dedicate ourselves to the topics around the pipe. But before we will take a look at this the answer of the sixth exercise. We will also have a quick review what we’ve learned so far in Part 6.
Review (Part 6)
Open ISE. Create a PowerShell Profile for all Users. Insert the command Start-Transcript in the first line. Save the file. Open PowerShell. What happend for all users?
This was a very good exercise. Some self-praise ;-). I was able to reconcile two things. Working with ISE and a introducing a new command: Start-Transcript. Well, let’s start with the creation of the PowerShell Profile for all users. As described in the last part we have to specify the all users path.
New-Item $profile.AllUsersAllHosts -Force
Next we have to open the created profile. I recommend notepad. Once opened, type Start-Transcript and click Save.
Now comes the magic moment. Close notepad and ISE and open PowerShell. As you can see PowerShell is recording now. Start-Transcript records all your inputs.
Now it’s up to you to test it. Enter a few commands and open the transcript file. The location of the file can be found in your user profile in the documents folder (as shown in the screenshot).
If you want to get powershell to do something at startup, create a PowerShell profile file. Be aware of the Execution Policy. The PowerShell ISE is a powerful script editor that can help you writing your scripts.
The PowerShell Pipe
Now we come to the next part. Working with the pipe. And this is a key part of the series. Let’s dive in.
The Windows PowerShell pipeline allows you to join two or more statements with a pipe symbol. Working with the pipe is a key technique in PowerShell. You can think of it as a kind of object-forwarding to other PowerShell commands. In concrete terms, the pipe takes everything on the left of the pipe and forwards it to the command to the right of the pipe.
First of all, the pipe symbol is located on your keyboard. You can find it on most keyboards here:
So, the goal for now it to combine two commands with a pipe to give you an example.
Working with the pipe is a key technique in PowerShell. In concrete terms, the pipe takes everything on the left of the pipe and forwards it to the command to the right of the pipe.
An example: Get-Process | Stop-Process
Many of you may think: “Hey, that’s nice, but what’s the point?” Now I am going to show you the power of the pipe in a simply example. Let’s say we want to close all Notepad and Paint processes. Well then let’s catch them all and pipe them to Stop-Process.
But wait a minute. Before we begin we take a look at the commands separately. On my computer there are 2 Notepad processes and 2 Paint processes.
That said, Get-Process catches all Notepad and all Paint processes. Remember: The pipe takes everything on the left of the pipe and forwards it to the command to the right of the pipe.
So, if we put Get-Process on the left side of the pipe and Stop-Process to the right side of the pipe then all this processes should be stopped.
Get-Process notepad,mspaint | Stop-Process
They are all gone. And if you put -verbose to the end of the command you’ll see that all processes stops immediately and that they all have different process ids.
Some more example to play with …
Stopping services …
Get-Service spool*,*bits* | Stop-Service -Verbose
Showing the newest 5 event logs from the system log in a nicely view with Out-GridView.
Get-EventLog -LogName system -Newest 5 | Out-GridView
Browsing the Windows setup log (located at C:\Windows\Panther) and searching the first successful boot entry during installation.
Get-ChildItem C:\Windows\Panther | Select-String 'First Boot'
Searching for unique entrys …
Get-Content C:\Temp\file1.txt | Get-Unique
or count something …
Get-Content -Path C:\Temp\file1.txt | Get-Unique | Measure-Object
To be more specific:
Get-Content -Path C:\Temp\file1.txt | Get-Unique | Measure-Object | Select-Object Count
For the further part I will concentrate on three commands. All of them have to do with formatting and the use of the pipe and they are perfectly suitable for beginners. Let’s move on.
What have we learned so far?
The pipe takes everything on the left of the pipe and forwards it to the command to the right of the pipe.
Piping to Format-Table, Format-List and Format-Wide
The Format-Table cmdlet formats the output of a command. And it’s used with the pipe.
Look at the command below. It shows you a table. The table headers are Mode, LastWriteTime, Length and Name.
This table is pre-defined. But the good news is we can modify the table to fit our needs. Pay attention to the table headers. They have a name. And this names are very important for us. How do you like that:
Get-ChildItem | Format-Table Name,LastWriteTime
All you need to know are the header table names. Then you can rearrange the output with Format-Table or you can simply omit things.
Let me give you another example. Get-Service displays all Windows services. Right?
But I don’t like this view. I only need the Status and the Name. This is an easy task. Simply pipe it to Format-Table and provide the Status and Name.
Get-Service | Format-Table Status,Name
More about Format-Table in the Microsoft Docs:
The default output is pre-configured by command. Some commands output too much information and that’s the reason that they are not displayed as a table, but as a list. Get-NetIPConfiguration is such a command.
We now know the list headers. Let’s pipe this command to Format-List and select only the IPv6Address and IPv4Address.
Get-NetIPConfiguration | Format-List IPv4Address,IPv6Address
Nice. Don’t be distracted by the brackets. In the background a WMI action is started that get’s the IP-Address. That’s what the brackets are for.
We can also format the output of Get-ChildItem to a list.
Get-ChildItem | Format-List Name,LastWriteTime
More about Format-List here:
Last, but not least the last command for today. It’s called Format-Wide and the name tells us what it does: Formatting something in a wide format.
Microsoft Docs to Format-Wide:
Format-Table, Format-List and Format-Wide adjusts the output of a command. Use it with a pipe.
Format-Table, Format-List, Format-Wide in Advanced Mode
That’s not the end of this article. Now I’m going to show you some interesting and useful stuff about formatting. It’s a small collection of my most useful formatting parameters.
The parameter adjusts the column size based on the width of the data.
Get-ChildItem C:\Temp | Format-Table -AutoSize
Displays text that exceeds the column width. By default, text that exceeds the column width is truncated.
Get-EventLog -LogName Security -Newest 2 | Format-Table -Wrap
Specify the number of columns.
Get-ChildItem | Format-Wide -Column 3
Some more examples … Active Directory (Side Note)
If you are working with Active Directory, you can also use the format commands to display users. Log in to a domain controller and start PowerShell. Here is some examples:
Get-AdUser administrator -Properties * | Format-Table CN,Enabled,LastLogonDate,SID -AutoSize -Wrap
Format-Table only makes sense with a few properties. Use Format-List to list more:
Get-ADUser administrator -Properties * | Format-List CN,Enabled,LastLogonDate,SID,Created,ProfilePath,ScriptPath,LockedOut
Or do it for all users with the Filter * parameter.
Get-ADUser -Filter * -Properties * | Format-Table CN,Enabled,LastLogonDate,SID -AutoSize -Wrap
Similarities with famous people from the film pumping iron are purely coincidental 😉
That’s it for today. Here’s the exercise up to the next part.
Run Get-Hotfix. Show only the number (KB) of the hotfix and the install date in list format.
The solution can be found in the next part.
Patrick Gruenauer, MVP PowerShell