Author Posts

March 23, 2017 at 1:54 pm

Hi there!

I have a problem to understand the way PowerShell handles properties in a pipe with multiple cmdlets. Let's have a look at an example. I'd like to have a list of all directories located in C:. The properties I'd like to see are FullName, CreationTime and Owner. I tried it with this one-liner:

Get-ChildItem C: | Get-Acl | Select-Object FullName, CreationTime, Owner

This does not work. The two properties FullName and CreationTime are not included in the Get-Acl cmdlet so these properties do not exists anymore when selected.

I know, there is a way to solve this with ForEach-Object:

Get-ChildItem C: | ForEach-Object {
    $Owner = (Get-Acl $_.FullName | Select-Object Owner).Owner
    Write-Host $_.FullName
    Write-Host $_.CreationTime
    Write-Host $Owner
    }

But this is not a very elegant way, imho. Is there a more elegant way to solve this? Maybe with a one-liner?

Thanks
LosPollos

March 23, 2017 at 2:07 pm

You can use calculated properties like this:

Get-ChildItem C: | Select-Object FullName, CreationTime, @{Name='Owner';Expression={(Get-Acl $_).Owner}}

March 23, 2017 at 2:19 pm

That's a pretty nice way to do it, actually. Though I wouldn't necessarily write-host it if you want to create a re-usable tool.

You could do:

    function Get-FileOwner () {
        [CmdletBinding()]
        param (
            # Path
            [Parameter(Mandatory)]
            [string]
            $Path
        )

        Get-ChildItem -Path $Path | ForEach-Object {
            [PsCustomObject]@{
                Owner = (Get-Acl $_.FullName).Owner
                FullName = $_.FullName
                CreationTime = $_.CreationTime
            }
        }
    }

That way from then on you only have to do Get-FileOwner -Path C: to get what you want. More than you asked for. Perhaps more than you need. I did take out the Select-Object Owner part because it was unnecessary, but I think you already had a fairly nice solution.

March 23, 2017 at 6:30 pm

I had just woken up when I wrote that .. in retrospect, I should've used: Get-ChildItem @PSBoundParameters so any of the advanced switches/options like -ErrorAction would follow into that cmdlet. Like: Get-FileOwner -Path C: -ErrorAction SilentlyContinue. Just a note. Hopefully one of the replies here has helped!

March 24, 2017 at 7:13 am

Thanks to both of you!

@Olaf: Nice way to use the calculated properties! It seems like calculated properties are more powerful than I thought. Thanks for that inspiration! 🙂

@Joshua: Yes, if I needed more than just Write-Host I would've probably worked with some kind of a way too complex array.. 🙂 I did not knew about [PsCustomObject] yet. It looks like a very interesting thing. I will have a deeper look at it!