Working with the new $PSItem automatic variable in Windows PowerShell 3.0

Editor’s note: The following post was written by PowerShell MVP Jan Egil Ring

Windows PowerShell has become a key skillset for IT Professionals, as we can see based on the massive amount of PowerShell support in the latest release of the Windows operating system. In this article, we are going to look at a new feature in the latest version of Windows PowerShell that shipped with Windows 8 and Windows Server 2012. There are many new enhancements in PowerShell 3.0. The purpose of this article is to show one of them, which will make it easier to get started with PowerShell.


One of the concepts which is difficult to understand when learning PowerShell is the use of the $_ automatic variable.


For example, consider that we are using Get-Service to retrieve all the services on a computer. If we want to filter out only services that are not running, we can use the Where-Object cmdlet.


Get-Service | Where-Object-FilterScript{$_.Status-eq"Stopped"}


The –FilterScript parameter is positional, meaning we do not need to specify the parameter if we pass the filter script block as the first parameter. This is the most common approach:



Get-Service | Where-Object {$_.Status -eq "Stopped"}


This syntax is not very easy to understand and remember, but there are enhancements in PowerShell 3.0 to make this easier. One of the enhancements is the new automatic variable called $PSItem. As with most things in PowerShell, the best place to look for documentation is the built-in help system. Run the following to bring a help windows for the about_Automatic_Variables topic:



Get-Help about_Automatic_Variables-ShowWindow


Type “psitem” in the Find box to highlight all text containing this word:



As we can see, $PSItem is the same as $_. The goal with the introduction of the $PSItem variable is making the code containing the “current object in the pipeline” easier to read and understand.

Now we are going to use the exact same example as above, replacing $_ with $PSItem:



Get-Service | Where-Object {$PSItem.Status -eq"Stopped"}


Another enhancement in terms of efficiency and readability is the new simplified syntax for Where-Object and Foreach-Object. The new syntax makes it possible to mitigate the curly brackets and the $_/$PSItem variable:



Get-Service | Where-ObjectStatus-eq "Stopped"


Note that one caveat regarding the simplified syntax is the limitation to one property. This means we still need to use the old syntax when filtering more than one property:


Get-Service | Where-Object {$PSItem.Status -eq"Stopped" -and$PSItem.DisplayName-like"*Windows*"}



For a new PowerShell user, it should be easier to understand what the $PSItem is referring to, compared to the old $_.propertyname syntax.

The $PSItem can also be used in other scenarios where we need to reference the current object in the pipeline, for example when using Select-Object to rename a property. This is an example using the old syntax:



Get-Service | Select-Object-PropertyName,@{Name="ServiceState";Expression={$_.Status}}


In PowerShell 3.0, we can simply replace $_ with $PSItem to make it more readable:



Get-Service | Select-Object-PropertyName,@{Name="ServiceState";Expression={$PSItem.Status}}


Since $PSItem is not available in previous versions of PowerShell, a good practice is to use the#requires –version 3 statement if using the variable in a script.

In conclusion, with the introduction of the new $PSItem automatic variable, as well as the simplified syntax for Where-Object and Foreach-Object, we are provided with better readability and efficiency.



What's New in Windows PowerShell 3.0

Windows Management Framework 3.0 (Includes Windows PowerShell 3.0, WMI, WinRM, Management OData IIS Extension, and Server Manager CIM Provider for down-level operating systems.)

Windows PowerShell 3.0 and Server Manager Quick Reference Guides


About the author

Jan Egil Ring works as a Lead Architect on the Infrastructure Team at Crayon, Norway.

He mainly works with Microsoft server-products, and has a strong passion for Windows PowerShell. In
addition to being a consultant, he is a Microsoft Certified Trainer.

He has obtained several certifications such as MCSE: Server Infrastructure and MCSE: Private Cloud.He is also amultiple-year recipient of the Microsoft Most Valuable Professional Award for
his contributions in the Windows PowerShell technical community.

Website               Twitter                 LinkedIn

About MVP Monday

The MVP Monday Series is created by Melissa Travers. In this series we work to provide readers with a guest post from an MVP every Monday. Melissa is a Community Program Manager, formerly known as MVP Lead, for Messaging and Collaboration (Exchange, Lync, Office 365 and SharePoint) and Microsoft Dynamics in the US. She began her career at Microsoft as an Exchange Support Engineer and has been working with the technical community in some capacity for almost a decade. In her spare time she enjoys going to the gym, shopping for handbags, watching period and fantasy dramas, and spending time with her children and miniature Dachshund. Melissa lives in North Carolina and works out of the Microsoft Charlotte office.