Created
February 1, 2021 04:12
-
-
Save jborean93/b5eba78e736e035b28e51f086390fa14 to your computer and use it in GitHub Desktop.
Get Windows Explorer metadata properties
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Copyright: (c) 2021, Jordan Borean (@jborean93) <[email protected]> | |
# MIT License (see LICENSE or https://opensource.org/licenses/MIT) | |
Update-TypeData -TypeName 'Shell.Metadata' -DefaultDisplayPropertySet 'Name', 'Item type' -Force | |
Function Get-ItemMetadata { | |
<# | |
.SYNOPSIS | |
Get shell explorer metadata for a file. | |
.DESCRIPTION | |
Get the metadata for for file or directory. Outputs a PSObject with properties relating to the localised file | |
metadata properties as seen by Windows Explorer. | |
.PARAMETER Path | |
The list of paths to get the metadata for, can include wildcards. | |
.PARAMETER LiteralPath | |
The list of literal paths to get the metadata for. | |
.NOTES | |
Uses the 'Shell.Application' COM object | |
#> | |
[CmdletBinding(DefaultParameterSetName='Path')] | |
[OutputType('Shell.Metadata')] | |
param ( | |
[Parameter( | |
Mandatory = $true, | |
Position = 0, | |
ValueFromPipeline = $true, | |
ValueFromPipelineByPropertyName = $true, | |
ParameterSetName = 'Path' | |
)] | |
[SupportsWildcards()] | |
[ValidateNotNullOrEmpty()] | |
[String[]] | |
$Path, | |
[Parameter( | |
Mandatory = $true, | |
Position = 0, | |
ValueFromPipelineByPropertyName = $true, | |
ParameterSetName = 'LiteralPath' | |
)] | |
[Alias('PSPath')] | |
[ValidateNotNullOrEmpty()] | |
[String[]] | |
$LiteralPath | |
) | |
begin { | |
$shell = New-Object -ComObject Shell.Application | |
} | |
process { | |
if ($PSCmdlet.ParameterSetName -eq 'Path') { | |
$allPaths = $Path | ForEach-Object -Process { | |
$provider = $null | |
$PSCmdlet.SessionState.Path.GetResolvedProviderPathFromPSPath($_, [ref]$provider) | |
} | |
} | |
elseif ($PSCmdlet.ParameterSetName -eq 'LiteralPath') { | |
$allPaths = $LiteralPath | ForEach-Object -Process { | |
$PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($_) | |
} | |
} | |
foreach ($filePath in $allPaths) { | |
if (-not (Test-Path -LiteralPath $filePath)) { | |
Write-Error -Message "Failed to find path $filePath" -Category ObjectNotFound | |
continue | |
} | |
$shellFolder = $shell.Namespace((Split-Path -Path $filePath -Parent)) | |
$shellFile = $shellFolder.ParseName((Split-Path -Path $filePath -Leaf)) | |
$metadata = [Ordered]@{ | |
PSTypeName = 'Shell.Metadata' | |
FullName = $filePath | |
} | |
$metaId = 0 | |
while ($true) { | |
$metaName = $shellFolder.GetDetailsOf($null, $metaId) | |
if ($metaName) { | |
$metaValue = $shellFolder.GetDetailsOf($ShellFile, $metaId) | |
$metadata.$metaName = $metaValue | |
} | |
elseif ($metaId -gt 300) { | |
# Don't know of a way to figure out the max number, I know that ~300 is around the max so just | |
# break the loop if the name is null and the id is >300. | |
break | |
} | |
$metaId += 1 | |
} | |
[PSCustomObject]$metadata | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment