EXIF data with PowerShell (Part 3)

Building off of my first two posts on interacting with EXIF metadata using PowerShell, reading the EXIF tag value and reading Lat and Long, I left off with calling Get-FileContents to create a file handle to a pass to Get-ExifContents and Get-ExifCoordinates and then return a custom PowerShell object that can be interacted with to output data to either the screen or to a CSV file. Below is a screenshot of calling the script with a JPG given as input.

So the script is called and a file is passed as a named parameter to script. The first lines of the script will accept parameters from the PowerShell prompt and override the default values.

1
2
3
4
5
6
7
8
param(
     [string]$file = $false,
     [string]$exportcsv = $false,
)

# Loads the System.Drawing DLL for usage
Add-Type -Assembly System.Drawing

To handle the System.Drawing DLL not being correctly loaded when calling it in Get-FileContents I called it at the beginning of the script. I set those two values as false so that I can respond to them in conditional statements further in the script. The next block of code in the script, Write-Results is a custom function to output the EXIF contents to the screen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Function Write-Results{
     param($label, $value)
     # Writes the property label to the output without a new line
     Write-Host "${label}: " -NoNewline
     if ($value -like "<empty>"){
          # if the EXIF data is not there writes the text in green text
          Write-Host $value -ForegroundColor DarkGreen
     }
     else {
          # If there is EXIF data write the data in red text
          Write-Host $value -ForegroundColor DarkRed
     }
}

By setting the “foreground” color, aka the text, it allows the output to be easily glanced at and determine if there is metadata associated to the tag. After that, the user is prompted to input the file path if the variable $file was not set when the script was called and is still $false. The next line creates an Array List, a PowerShell object that is a mutable list, that will be used to store the metadata objects as returned after parsing the JPGs. Next, using the .NET framework, the script checks to see if the $file variable is a directory. If it’s a directory, it creates a list of files in the directory and calls Get-FileContents for each JPG and stores the PowerShell object in the array list. And if it’s not a directory, it will add the output of Get-FileContents to the array list.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# Prompts the user for the file path if it was not given upon invocation
if (!$file){
     $file = Read-Host -Prompt "Path to photo to inspect"
}

$exportArray = [System.Collections.ArrayList]@()
$isDir = (Get-Item $file) -is [System.IO.DirectoryInfo]
# Write-Output "isDir: $isDir"

if ($isDir){
     $fileList = (Get-ChildItem $file).fullname
     foreach($childFile in $fileList){
          $ext = (Get-ChildItem $childFile).extension
          if($ext -ne ".jpg"){
               Write-Output "$childFile is not a jpg, skipping"
               continue
          }
          $obj = Get-FileContents($childFile)
          $exportArray.add($obj) | Out-Null
          
     }
}

else {
     $ext = (Get-ChildItem $file).extension
     if($ext -notlike ".jpg"){
          Write-Output "$file does not have .jpg extension"
          exit
     }
     $obj = Get-FileContents($file)
     $exportArray.add($obj) | Out-Null
}

At this point, we now have an Array list of PowerShell objects containing the metadata for the JPGs that we can interact with. I piped $exportArray.add($obj) to Out-Null so that the object will not be output to the screen when called. The only thing still required to mark the script complete at this point before adding the ability to remove the metadata from the JPGs is to either print the output to the screen or export it to a CSV. The following code is pretty much self-explanatory to finish this script up. When exporting the Array list, if desired, the first row in the CSV is headers containing the keys identified in the PS object. If exporting to a CSV was not specified the program will then output the results to the screen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
if ($exportcsv){
     $exportArray | Export-Csv -NoTypeInformation -Append $exportcsv
}

if ($exportcsv -eq $false){
     # Writes the results to the screen for veiwing
     foreach($obj in $exportArray){
          Write-Host Picture: $obj.file
          Write-Results -label "Camera Maker" -value $obj.cameramaker
          Write-Results -label "Camera Model" -value $obj.cameramodel
          Write-Results -label "Software Version" -value $obj.softwareversion
          Write-Results -label "Time Taken" -value $obj.datetaken
          Write-Results -label "Latitude" -value $obj.latitude
          Write-Results -label "Longitude" -value $obj.longitude
          Write-Results -label "Altitude" -value $obj.altitude
     }
}

Stay tuned for part 4 where I remove the metadata and post the full script.

Leave comment

Your email address will not be published. Required fields are marked with *.