none
access DateImported

    Question

  • There is a value just for picture files, DateImported. Since a lot of programs don't give access to it for sorting and such I would like to write a script that would assign the DateImported to the LastWriteTime. Something like:

    PS C:\> (ls test.jpg).LastWriteTime = (ls test.jpg).DateImported

    Except it doesn't know what DateImported is when I try it that way. Any ideas?

    Thanks

    Friday, July 19, 2013 11:05 PM

Answers

  • I think this is one of the fields exposed by the Property System API (http://msdn.microsoft.com/en-us/library/windows/desktop/ff728871(v=vs.85).aspx), which does not appear to be exposed through the .NET Framework.  You could use P/Invoke to call all the Win32 API functions from PowerShell, but the code would be very complicated.

    As an alternative, you could download prop.exe from http://prop.codeplex.com/ , use the prop.exe dump command, and parse its output.  Something like this:

    $DirectoryToSearch = 'C:\Users\Dave\Pictures'
    
    Get-ChildItem -Path $DirectoryToSearch -Recurse |
    Where-Object { $_.PSIsContainer -eq $false } |
    ForEach-Object {
        $output = .\prop.exe dump -file:"$($_.FullName)"
        $found = $false
    
        foreach ($line in $output) {
            if ($line -match '^System\.DateImported:\s*(.+)$') {
                $found = $true
    
                [System.DateTime] $dateImported = New-Object System.DateTime
                if ([DateTime]::TryParse($matches[1], [ref] $dateImported)) {
                    Write-Host "$($_.FullName): Setting LastWriteTime to '$dateImported'"
                    
                    # Uncomment the next line to actually make changes
                    # $_.LastWriteTime = $dateImported
                } else {
                    Write-Host "$($_.FullName): Error parsing date/time value '$($matches[1])'"
                }
    
                break
            } 
        }
    
        if ($found -eq $false) {
            Write-Host "$($_.FullName): No DateImported field present."
        }
    }
    

    • Edited by David WyattMVP Saturday, July 20, 2013 5:21 AM edit
    • Marked as answer by Njem2 Wednesday, July 24, 2013 3:25 PM
    Saturday, July 20, 2013 5:19 AM

All replies

  • I think this is one of the fields exposed by the Property System API (http://msdn.microsoft.com/en-us/library/windows/desktop/ff728871(v=vs.85).aspx), which does not appear to be exposed through the .NET Framework.  You could use P/Invoke to call all the Win32 API functions from PowerShell, but the code would be very complicated.

    As an alternative, you could download prop.exe from http://prop.codeplex.com/ , use the prop.exe dump command, and parse its output.  Something like this:

    $DirectoryToSearch = 'C:\Users\Dave\Pictures'
    
    Get-ChildItem -Path $DirectoryToSearch -Recurse |
    Where-Object { $_.PSIsContainer -eq $false } |
    ForEach-Object {
        $output = .\prop.exe dump -file:"$($_.FullName)"
        $found = $false
    
        foreach ($line in $output) {
            if ($line -match '^System\.DateImported:\s*(.+)$') {
                $found = $true
    
                [System.DateTime] $dateImported = New-Object System.DateTime
                if ([DateTime]::TryParse($matches[1], [ref] $dateImported)) {
                    Write-Host "$($_.FullName): Setting LastWriteTime to '$dateImported'"
                    
                    # Uncomment the next line to actually make changes
                    # $_.LastWriteTime = $dateImported
                } else {
                    Write-Host "$($_.FullName): Error parsing date/time value '$($matches[1])'"
                }
    
                break
            } 
        }
    
        if ($found -eq $false) {
            Write-Host "$($_.FullName): No DateImported field present."
        }
    }
    

    • Edited by David WyattMVP Saturday, July 20, 2013 5:21 AM edit
    • Marked as answer by Njem2 Wednesday, July 24, 2013 3:25 PM
    Saturday, July 20, 2013 5:19 AM
  • It's probably one of the ExIf data.

    Using a few classes in System.Drawings, I wrote this script to expose some of the EXIF data of a JPG file.

    $image = New-Object System.Drawing.Bitmap('C:\Test.JPG')
    $myPropertyItems = @()
    foreach($propertyItem in $image.PropertyItems)
    {
        $id = '0x{0}' -f $propertyItem.'Id'.ToString('x')
        $length = $propertyItem.'Len'
        $orgValue = $propertyItem.'Value'
        $newValue = $null
        switch ($propertyItem.'Type')
        {
            2 { $newValue = [System.Text.Encoding]::Default.GetString($orgValue); break }
            3 { $newValue = @(); for ($counter = 0; $counter -lt [int]($length * 8 / 16); $counter++) { [uint16]$newValueElement = 0; for ($counter2 = 0; $counter2 -lt (16/8); $counter2++) { $newValueElement += $orgValue[8 * $counter + $counter2] * [Math]::Pow(8,$counter2) }; $newValue += $newValueElement }; break }
            {($_ -eq 4) -or ($_ -eq 5)} { $newValue = @(); for ($counter = 0; $counter -lt [int]($length * 8 / 32); $counter++) { [uint32]$newValueElement = 0; for ($counter2 = 0; $counter2 -lt (32/8); $counter2++) { $newValueElement += $orgValue[8 * $counter + $counter2] * [Math]::Pow(8,$counter2) }; $newValue += $newValueElement }; break }
            {($_ -eq 7) -or ($_ -eq 10)} { $newValue = @(); for ($counter = 0; $counter -lt [int]($length * 8 / 32); $counter++) { [int32]$newValueElement = 0; for ($counter2 = 0; $counter2 -lt (32/8); $counter2++) { $newValueElement += $orgValue[8 * $counter + $counter2] * [Math]::Pow(8,$counter2) }; $newValue += $newValueElement }; break }
            default { $newValue = $orgValue }
        }
        $props = [ordered]@{'ID'=$id;'Len'=$length;'Type'=$($propertyItem.'Type');'Value'=$newValue}
        $myPropertyItems += New-Object PSObject -Property:$props
    }
    $myPropertyItems | Format-Table -AutoSize
    $image.Dispose()

    References:

    Reading Photo Metadata: http://www.developerfusion.com/article/84474/reading-writing-and-photo-metadata

    Image.Get-PropertyItem method: http://msdn.microsoft.com/en-us/library/ms535390.aspx

    List of PropertyItem.Type: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.propertyitem.type.aspx

    PropertyItem.ID List defined in MSDN: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.propertyitem.id.aspx

    Similar question for a C# solution:  http://stackoverflow.com/questions/58649/how-to-get-the-exif-data-from-a-file-using-c-sharp


    Saturday, July 20, 2013 5:56 AM
  • David,

    Thanks so much for this. I had a little trouble using it and some adaptations I needed to make but it got me in the right direction and working now.

    Thanks.

    Wednesday, July 24, 2013 3:25 PM