- Create a certificate-signed RDP shortcut via Group Policy - Fri, Aug 9 2019
- Monitor web server uptime with a PowerShell script - Tue, Aug 6 2019
- How to build a PowerShell inventory script for Windows Servers - Fri, Aug 2 2019
You probably know PowerShell is all about objects. Objects are what make PowerShell great! By nature, all objects have properties, and we can read those properties by various means. The native objects we get back from commands like Get-Process, Get-Service, and a plethora of other commands are usually just fine. But sometimes the properties returned on an object need to change a little bit.
Perhaps you're building a report and need to display a few extra properties to export them correctly. Or maybe you need to tweak an existing property ever so slightly to get it in the format you'd like to see. For these reasons, we have calculated properties in PowerShell.
We can use the calculated properties feature with the Select-Object cmdlet to change or even add additional object properties as PowerShell returns them. Select-Object is a common cmdlet typically used in PowerShell either to show all properties on an object or to limit the default properties shown.
For example, by default, Get-Service will only show a limited number of properties.
If we pipe that same output to Select-Object using the Property parameter, we can show all objects, for example.
Using Select-Object with the Property parameter allows us to choose which properties to show. However, what if we want to add a custom property to the output or modify an existing property's value? For these situations, we can use calculated properties.
Instead of simple strings like Name, DisplayName, and such, PowerShell represents calculated properties with a hash table containing the name of the property to return and an expression. A script block represents the latter and contains the code to execute and generate the value. For a comparison, here's how we'd display the Name property that Get-Service returns:
Get-Service | Select-Object -Property Name
Here's how we could do the same but by using a calculated property:
Get-Service | Select-Object -Property @{Name = 'Name'; Expression = {$_.Name}}
The example above doesn't make a whole lot of sense because we wouldn't need a calculated property if just displaying the Name property. The example does show how to structure the hash table.
Notice a script block is inside of the Expression key. Inside of that script block, we can reference each object coming from Get-Service with the pipeline variable. For that matter, any object property or method is available for use.
To show a good example of calculated properties, take a look at the default output of Get-Service displayed in the screenshot above. Notice it does not show the path to the EXE the service is controlling. The EXE path is not a property that Get-Service returns natively. But by using calculated properties, we can "add" this property to the output by grabbing that value for each service that comes down the pipeline.
First, we need to figure out where to get the EXE path for each service. To do this, we can dip into the Win32_Service WMI class and gather it using Get-CimInstance. Below, I'm only returning the path for all services and assigning them to a variable. I grab all services ahead of time because if not, I would have had to issue a WMI query for every service, which would be inefficient coding.
$wmiServices = Get-CimInstance -ClassName win32_service -Property Name,PathName
Now that we have all the paths for each service safely stored in a variable, we can now add the code necessary to find the path for each service inside of the Expression script block.
Get-Service | Select-Object -Property *,@{Name = 'PathName'; Expression = { $serviceName = $_.Name; (@($wmiServices).where({ $_.Name -eq $serviceName })).PathName }}
Notice also that I had to still include the * as an element passed to the Property parameter since I still wanted to see all the other properties as well.
Subscribe to 4sysops newsletter!
Calculated properties are a great way to manipulate the properties that a command returns. By piping output from commands to Select-Object and using a hash table instead of a string for the Property parameter argument, you're able to return just about any object property you desire!
Woaow! I am impressed by “@($wmiServices).where…….”
That’s efficient coding!
Like I already told you, even if I know the topic,
I read your posts anyway because I often find some gems inside 😉
I’m glad you’re getting some good stuff out of my content!
Thanks mate, that’s really clean example.
That's really a classic. – Due to unknown reason my cells can't remember the syntax so I keep visiting this site.
Many thanks for it 🙂
Very nice! Which command would you use if you want to change the Property value?
For example: Property 'CanStop' is set to 'False', how can I change it to 'True'?
Regards!
Hi
Are you able to help with the following.
This works fine in a PowerShell command line but fails when copied into a one liner script
Further to the confusion
replacing the username with a real user in the following one liner works both in a command line PowerShell and in a PowerShell script
Get-ADUser "username" -Properties "DisplayName", "msDS-UserPasswordExpiryTimeComputed" | Select-Object -Property "Displayname",@{Name="ExpiryDate";Expression={[datetime]::FromFileTime($_."msDS-UserPasswordExpiryTimeComputed")}}
It doenst work for you because the property PasswordNeverExpires is not normally returned by Get-ADUser unless you specifically ask for it via -Properties parameter. So you cant use it in the initial filter.
ok, got it working in a script
hehe your right, my previous answer was incorrect. Shame on me 🙂