5
\$\begingroup\$
Function Enumerate-Properties($fileName)
{
    $path = (Get-Item $fileName).FullName
    $shell = New-Object -COMObject Shell.Application
    $folder = Split-Path $path
    $file = Split-Path $path -Leaf
    $shellfolder = $shell.Namespace($folder)
    0..287 | Foreach-Object {'{0} = {1}' -f $_, $shellfolder.GetDetailsOf($null, $_)}
}
Function Find-Property($fileName, $PropertyName)
{
    $shell = New-Object -COMObject Shell.Application
    $path = (Get-Item $fileName).FullName
    $folder = Split-Path $path
    $file = Split-Path $path -Leaf
    $shellfolder = $shell.Namespace($folder)
    $shellfile = $shellfolder.ParseName($file)
    $found = $false
    0..287 | Foreach-Object {
        $test1 = $shellfolder.GetDetailsOf($null, $_)
        if($PropertyName -eq $shellfolder.GetDetailsOf($null, $_))
        {
            $found = $true
            return $_
            break
        }
    }
    if(!$found)
    {
        Write-Host "Property "$PropertyName " was not found"
    }
}
Function Get-PropertyValue($fileName, $property)
{
    $shell = New-Object -COMObject Shell.Application
    $path = (Get-Item $fileName).FullName
    $folder = Split-Path $path
    $file = Split-Path $path -Leaf
    $shellfolder = $shell.Namespace($folder)
    $shellfile = $shellfolder.ParseName($file)
    return $shellfolder.GetDetailsOf($shellfile,$property)
}
Function Create-List3($files, $property)
{
    $array = @()
    $propertyNum = Find-Property $files[0] $property
    foreach($file in $files)
    {
        $file | Add-Member -MemberType noteproperty -Name $property -Value (Get-PropertyValue $file $propertyNum).toString() -force
        $array = $array + $file
    }
    return $array
}

This code is designed to be used in something like the following fashion:

$files = dir *.mp4
$propery = "Bit rate"
$array = Create-List3 $files $property
$array | Format-Table Name, Length, $property -auto

As far as I can tell, this code works when you give it a nice amount of .mp4 files. It fares less well when handed other things (folders and the like), the break statement in the Find-Property does nothing (and there has to be a better way to do that anyway).

I am mostly concerned that while this is valid Powershell code, it is very poor Powershell code, in that it is written in a psudo-C# style (that is where I am coming from) and not a Powershell style.

Additionally, I am positive that there easier ways to set up the COM Objects that I am using, and parsing filenames (and reusing them, but that is more complex probably).

How can I make this code better idiomatic Powershell?

\$\endgroup\$
4
\$\begingroup\$

A first thing to note is that you are creating a lot of COMObjects in a similar manner, we can simply extract that behavior as a separate function. Then, we note that you are expecting file names as parameters where you could expect an item instead; that allows you to pass on items to Create-List3 instead, thus allowing for piping Get-ChildItem into rather than doing extra conversion calls back and forth.

As a result of this two things we're left with a lot of Split-Path calls, we can simply port them over to extracted function as well, it appared that you only needed one of the Split-Pat calls only once. After that, some small cleanup has been done (removing $test1, adding extra newlines and spaces for readability) and we already have much cleaner code to continue from:

Function Get-ShellFolder($fileItem)
{
    $folder = Split-Path $fileItem.FullName

    $shell = New-Object -COMObject Shell.Application
    return $shell.Namespace($folder)
}

Function Enumerate-Properties($fileItem)
{
    $shellfolder = Get-ShellFolder $fileItem

    0..287 | Foreach-Object {'{0} = {1}' -f $_, $shellfolder.GetDetailsOf($null, $_)}
}

Function Find-Property($fileItem, $PropertyName)
{
    $shellfolder = Get-ShellFolder $fileItem

    $found = false
    0..287 | Foreach-Object {
        if ($PropertyName -eq $shellfolder.GetDetailsOf($null, $_))
        {
            $found = true
            return $_
            break
        }
    }

    if (!$found) {
        Write-Host "Property " $PropertyName " was not found"
    }
}
Function Get-PropertyValue($fileItem, $property)
{
    $shellfolder = Get-ShellFolder $fileItem

    $file = Split-Path $fileItem.FullName -Leaf
    $shellfile = $shellfolder.ParseName($file)

    return $shellfolder.GetDetailsOf($shellfile, $property)
}
Function Create-List3($files, $property)
{
    $array = @()
    $propertyNum = Find-Property $files[0] $property
    foreach($file in $files)
    {
        $file | Add-Member -MemberType noteproperty -Name $property -Value (Get-PropertyValue $file $propertyNum).toString() -force
        $array = $array + $file
    }
    return $array
}

From here on, you could look for things that are already implemented in Powershell to make the code even more simple, as well as adding documentation to make some less obvious things easier to understand for fellow readers.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.