Accessing a Property of All Objects in a PowerShell Array

If you've looked at the scripts that I've written, you may have noticed that I use a fairly simple bit of syntax whenever I need to access a single property from all objects in an array (in PowerShell).  I just wrote that sentence and even I'm not entirely sure what it means, so I'd better use an example.  Try this:

$events = get-eventlog -newest 10
$events.source

What output did you see?  If you saw a list of 10 sources, congratulations, your PowerShell is at least version 3!  If you saw no output, then you should really update your PowerShell.  This is the functionality that I mean - the ability to easily generate an array of a single Property (in this case, Source) from an array of objects.

I bring this up because that functionality is super useful.  For example, I was recently writing a script for a customer that involved analyzing a bunch of AD Users and I needed to manipulate a single Property and then select users based on that Property (I'm still trying to decide if that script is too customer specific or if it's worth posting).  I was working on one of their desktops (since their security policy does not allow consultants to plug in to their network) and was trying to use that functionality like this:

foreach ($accountName in $allUsers.samaccountname)
{
...
}

and it just wasn't working!  A bit of troubleshooting revealed that $accountName was always null, despite the fact that $allUsers was a populated array and each object had a samaccountname Property.  Scratching my head, I modified my code to use this structure instead:


foreach ($thisUser in $allUsers)
{
$accountName = $thisUser.samaccountname
...
}

and it worked fine.  I had no idea why the first structure had not worked; I was beginning to feel like I was going crazy.  After a good night's rest, it came to me: PowerShell version!  It turned out that the desktop that they had given me still had the default Windows 7 PowerShell, which is Version 2.  I updated to Version 4 and, wouldn't you know it, that familiar first syntax worked fine.

So, if you find that any of my example scripts are mysteriously failing, take a look at your $PSVersionTable variable and see what version of PowerShell your workstation has installed.  You'll save yourself some headache as well as gain some great new features by updating to the latest and greatest!

Comments

  1. This is a PowerShell 3 feature called the automatic foreach.

    Source:
    http://blogs.technet.com/b/heyscriptingguy/archive/2012/08/20/my-five-favorite-powershell-3-0-tips-and-tricks.aspx

    Details:
    In Windows PowerShell 1.0 and Windows PowerShell 2.0, if you have a collection of objects, you must iterate through that collection, individually retrieve a desired property, and then possibly store it back in the variable for later use. It worked, and the behavior was similar to the behavior in other languages. In fact, this behavior still works in the Windows PowerShell 3.0 world today. Here is an example of using the Get-Process cmdlet where I store the collection of process objects in a variable named $process, and then pipe the resulting objects to the Foreach-Object cmdlet to retrieve the name property from the current object in the pipeline. I store these retrieved names in a $names variable.

    $process = Get-Process

    $Names = $process | foreach { $_.name }

    $names

    This command sequence is not that difficult, and it is one that the enterprise scripter will eventually type hundreds and hundreds of times over the course of a couple years. But in Windows PowerShell 3.0 this sequence is no longer required, and entire $process pipeline to the Foreach-Object command sequence is eliminated. Instead, Windows PowerShell 3.0 makes desired properties immediately available, and directly accessible. This revision of commands is shown here.

    $process = Get-Process

    $process.name

    Although simply displaying process names may be somewhat illuminating, this sequence saves me tons of time when I am gathering the names of servers to use in further remoting scenarios. This sequence is shown here.

    $servers = Get-ADComputer –Filter *

    Get-HotFix –CN ($servers.name)

    ReplyDelete

Post a Comment

Sorry guys, I've been getting a lot of spam recently, so I've had to turn on comment moderation. I'll do my best to moderate them swiftly after they're submitted,

Popular posts from this blog

PowerShell Sorting by Multiple Columns

Clone a Standard vSwitch from one ESXi Host to Another

Deleting Orphaned (AKA Zombie) VMDK Files