none
PowerShell script to read metadata info from pictures RRS feed

  • Question

  • Hi Guys,

    I'm new to powershell scripts. I need a help with the below code:

    Function Get-FileMetaData
    {
    
    Param([string[]]$folder)
    foreach($sFolder in $folder)
    {
    $a = 0
    $objShell = New-Object -ComObject Shell.Application
    $objFolder = $objShell.namespace($sFolder)
    
    foreach ($File in $objFolder.items())
    {
    $FileMetaData = New-Object PSOBJECT
    for ($a ; $a -le 266; $a++)
    {
    if($objFolder.getDetailsOf($File, $a))
    {
    $hash += @{$($objFolder.getDetailsOf($objFolder.items, $a)) =
    $($objFolder.getDetailsOf($File, $a)) }
    $FileMetaData | Add-Member $hash
    $hash.clear()
    } #end if
    } #end for
    $a=0
    $FileMetaData
    } #end foreach $file
    } #end foreach $sfolder
    } #end Get-FileMetaData
    
    $picdata = Get-FileMetaData -Folder 'C:\Users\mohad\Desktop\Shell\image' | select name, Dimensions, size, width, height
    $picdata
    
    


    My need is below:

    1. I'm converting this code into exe, so the script should give info abt all the images from the folder in which it is started (the folder will always be named as "images" )
    2. The result should be stored in a csv file name as "image data".
    3. I want to extract additional info such as "horizontal/vertical resolution' of an image, color representation etc.

    please help me!! TIA

    Saturday, October 24, 2015 8:21 AM

Answers

  • This is that:

     Get-FileMetaData <foldername> |select height,width,'horizontal resolution','vertical resolution'

    You just have to specify which properties you want out of the 256 that are captured.


    \_(ツ)_/

    Saturday, October 24, 2015 2:02 PM
    Moderator
  • That's because you are piping $picdata to the Export-CSV cmdlet, but you have never set $picdata equal to any value.  I suspect you intended for $picdata to contain the return data from your Get-FileMetaData function.

    $picdata = Get-FileMetaData $Env:userprofile\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution'
    $picdata | Export-csv $Env:userprofile\Desktop\Shell\image\exportfile.csv

    Or you can pipe your Get-FileMetaData directly to the Export-CSV cmdlet without using a variable at all

    Get-FileMetaData $Env:userprofile\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution' |
     Export-csv $Env:userprofile\Desktop\Shell\image\exportfile.csv


    Tuesday, October 27, 2015 9:48 PM
  • In PowerShell the most efficient way I know to retrieve the username (sAMAccountName) of the current domain user is with the ADSystemInfo object:

    $SysInfo = New-Object -ComObject "ADSystemInfo"
    $UserDN = $SysInfo.GetType().InvokeMember("UserName", "GetProperty", $Null, $SysInfo, $Null)
    $UserDN
    $User = [ADSI]"LDAP://$UserDN"
    $UserName  = $User.sAMAccountName

    Or, you can retrieve the value of the environment variable "username", but if the user is logged on locally you will get the local username. The above will raise an error if the user is not authenticated to a domain. From the environment:

    $User = $env:username


    Richard Mueller - MVP Directory Services


    Saturday, October 24, 2015 4:08 PM

All replies

  • Assuming you have a working function (there is a word wrap problem in what you posted that must not be in your original):

    Look at help for the Export-Csv cmdlet. You can pipe $picdata to this cmdlet to export the output to a CSV. To get the help run:

    Get-Help Export-Csv

    To see what properties are available from the function, do not pipe the output to the Select. You should get all available properties. Pipe to FT instead.

    $picdata = Get-FileMetaData -Folder 'C:\Users\mohad\Desktop\Shell\image' | FT
    $picdata

    After you see the properties, pick the ones you want, replace the FT with the Select where you list the properties you want. Then pipe $picdata to Export-Csv.

    Richard Mueller - MVP Directory Services

    Saturday, October 24, 2015 10:08 AM
  • To read image EXIF data you must use a tool designed to read EXIF data.  Windows cannot read this data with any native API.  What you see are the common image EXIF properties which are hard coded into the shell.

    The issue is that every imaging device vendor adds EXIF data in a proprietary format.  Alos different imaging standards use custom extensions to the image metadata.

    start here: https://en.wikipedia.org/wiki/Exchangeable_image_file_format

    and: http://www.codeproject.com/Articles/47486/Understanding-and-Reading-Exif-Data


    \_(ツ)_/

    Saturday, October 24, 2015 10:39 AM
    Moderator
  • Here is a good tutorial: http://blogs.technet.com/b/heyscriptingguy/archive/2014/02/06/use-powershell-to-find-metadata-from-photograph-files.aspx

    You will find that much of the camera data is in binary and has to be decoded.


    \_(ツ)_/


    • Edited by jrvModerator Saturday, October 24, 2015 10:42 AM
    Saturday, October 24, 2015 10:42 AM
    Moderator
  • Thanks a lot for your answer. I'm new to programming and very new to powershell. I have managed to put this code together with great struggle and need the tweaks to be done. Can you please help me with modifying the code? like what should be replaced with what ? It would be of great help.
    Saturday, October 24, 2015 10:49 AM
  • Thanks a ton for your reply . I'm new to programming and very new to powershell. I have managed to put this code together with great struggle and need the tweaks to be done.

    The things which you are mentioning appears very technical to me. Can you please help me with the code? I just need the image info such as heihgt width size vertical/horizontal resolution etc.

    Saturday, October 24, 2015 10:51 AM
  • Sorry but I cannot do this for you. The forum can answer specific questions about scripting but is not intended as a free code writing forum.

    I suggest purchasing or downloading one of the numerous tools that can read EXIF data.  PowerShell cannot read EXIF data.  The Shell metadata is all you can get.  The camera data is in the extended EXIF.  Microsoft Photo Viewer can display some common camera data.  For specific camera data we usually have to use the vendors tools.  For example, Nikon provides extra camera data and also provides a viewer that can read it.

    If the file metadata does not have what you want then you will have to use a different tool.

    You can also get raw image data with the System.Drawing classes.  This requires advanced scripting skills.  Search for examples.


    \_(ツ)_/

    Saturday, October 24, 2015 11:39 AM
    Moderator
  • Here is a better version that gets up to 256 properties. I ran it against my Nikon and Scanner data and all of the EXIF data is missing,  Only the basic and common items are read by Windows.

    Function Get-FileMetaData{
    	Param (
    		[Parameter(
    			Mandatory = $true,
    			ValueFromPipeline=$true
    		)][string]$FolderPath
    	)
    	
    	begin{
    		$shell = New-Object -ComObject Shell.Application
    	}
    	
    	Process {
    		$FolderPath
    		$folder = $shell.namespace($FolderPath)
    		$index=@{}
    		for ($i = 0; $i -lt 256; $i++) {
    			if ($tag = $folder.GetDetailsOf('.', $i)) {
    				Try{
    					$index.Add($tag, $i)
    				}
    				Catch{ Write-Host $tag  -fore green}
    			}
    		}
    		
    		foreach ($fi in $folder.items()) {
    			$data=@{}
    			$index.GetEnumerator() |
    			ForEach-Object{
    				$value = $folder.getDetailsOf($fi, $_.Value)
    				$data.Add($_.Name, $value)
    			}
    			[pscustomobject]$data
    		}
    		
    	}
    }
    
    
    
    


    \_(ツ)_/

    Saturday, October 24, 2015 12:30 PM
    Moderator
  • Good thing I looked.

    Scott Hanselmann has don a blog on how to use a free DLL to get picture data in PowerShell.

    http://www.hanselman.com/blog/AccessingEXIFPhotoDataFromJPEGsWithPowerShell.aspx

    I am pretty sure that it will not get the extended camera data because it is not vendor specific and I see no facility to add vendor IDs to the mix.


    \_(ツ)_/

    Saturday, October 24, 2015 12:41 PM
    Moderator
  • Hiii, Thanks a jillion for your help..I will try out the code and keep you posted..

    FYI, I just want an images basic information such as height width size vertical/horizontal resolution etc.

    -> making sure the converted exe runs in the folder from where it is executed (NOTE: The exe will be used by different users).

    -> The result should be imported to a csv file in the same place where the exe is present.

    I dont want the camera model etc etc or any other complicated info from an image.  The code which I posted above gave all the details...Have I misunderstood something here? 


    Saturday, October 24, 2015 1:13 PM
  • This is that:

     Get-FileMetaData <foldername> |select height,width,'horizontal resolution','vertical resolution'

    You just have to specify which properties you want out of the 256 that are captured.


    \_(ツ)_/

    Saturday, October 24, 2015 2:02 PM
    Moderator
  • Ok is it possible to read only selected properties instead of all the 256? Cos in case if a folder has 100 images, then the time to read all this and display the O/p will take long time
    Saturday, October 24, 2015 2:07 PM
  • And as I explained, you can use the function without the Select to see what it retrieves. Then you can select the ones you want by name.

    Richard Mueller - MVP Directory Services

    Saturday, October 24, 2015 2:07 PM
  • Ok is it possible to read only selected properties instead of all the 256? Cos in case if a folder has 100 images, then the time to read all this and display the O/p will take long time

    See my last post.  It has an example.


    \_(ツ)_/

    Saturday, October 24, 2015 2:19 PM
    Moderator
  • I used the below code for selecting the property :


    Get-FileMetaData C:\Users\mohad\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution'

    But here, we should mention the path from where the image details should be fetched. But when i convert this into exe and distributed to others, the username will differ and the exe wont run. is there a way to solve this?


    Saturday, October 24, 2015 2:41 PM
  • I used the below code for selecting the property :


    Get-FileMetaData C:\Users\mohad\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution'

    But here, we should mention the path from where the image details should be fetched. But when i convert this into exe and distributed to others, the username will differ and the exe wont run. is there a way to solve this?


    Instead of hard coding the path in your code, you should use the "$Env:USERPROFILE" environmental variable to get the profile path if the directory is always going to be on the user's desktop in a Shell\image folder.  Otherwise, you need to either have you script prompt for input or make your path relative to your script.
    Saturday, October 24, 2015 2:53 PM
  • OK so is this the format to be used ?:

    Get-FileMetaData $Env:userprofile\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution'

    Saturday, October 24, 2015 3:15 PM
  • In PowerShell the most efficient way I know to retrieve the username (sAMAccountName) of the current domain user is with the ADSystemInfo object:

    $SysInfo = New-Object -ComObject "ADSystemInfo"
    $UserDN = $SysInfo.GetType().InvokeMember("UserName", "GetProperty", $Null, $SysInfo, $Null)
    $UserDN
    $User = [ADSI]"LDAP://$UserDN"
    $UserName  = $User.sAMAccountName

    Or, you can retrieve the value of the environment variable "username", but if the user is logged on locally you will get the local username. The above will raise an error if the user is not authenticated to a domain. From the environment:

    $User = $env:username


    Richard Mueller - MVP Directory Services


    Saturday, October 24, 2015 4:08 PM
  • OK so is this the format to be used ?:

    Get-FileMetaData $Env:userprofile\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution'

     

    yes, that should do it.
    Saturday, October 24, 2015 4:12 PM
  • I used the below code:


    Function Get-FileMetaData{
    	Param (
    		[Parameter(
    			Mandatory = $true,
    			ValueFromPipeline=$true
    		)][string]$FolderPath
    	)
    	
    	begin{
    		$shell = New-Object -ComObject Shell.Application
    	}
    	
    	Process {
    		$FolderPath
    		$folder = $shell.namespace($FolderPath)
    		$index=@{}
    		for ($i = 0; $i -lt 256; $i++) {
    			if ($tag = $folder.GetDetailsOf('.', $i)) {
    				Try{
    					$index.Add($tag, $i)
    				}
    				Catch{ Write-Host $tag  -fore green}
    			}
    		}
    		
    		foreach ($fi in $folder.items()) {
    			$data=@{}
    			$index.GetEnumerator() |
    			ForEach-Object{
    				$value = $folder.getDetailsOf($fi, $_.Value)
    				$data.Add($_.Name, $value)
    			}
    			[pscustomobject]$data
    		}
    		
    	}
    }
    
    Get-FileMetaData $Env:userprofile\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution'
    $picdata | Export-csv $Env:userprofile\Desktop\Shell\image\exportfile.csv

    But I'm getting this error message while writing the data into a CSV:

    Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
    At C:\Users\mohad\Desktop\Shell\micro.ps1:40 char:12
    + $picdata | Export-csv $Env:userprofile\Desktop\Shell\image\exportfile.csv
    +            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand
    W





    Monday, October 26, 2015 3:48 AM
  • That's because you are piping $picdata to the Export-CSV cmdlet, but you have never set $picdata equal to any value.  I suspect you intended for $picdata to contain the return data from your Get-FileMetaData function.

    $picdata = Get-FileMetaData $Env:userprofile\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution'
    $picdata | Export-csv $Env:userprofile\Desktop\Shell\image\exportfile.csv

    Or you can pipe your Get-FileMetaData directly to the Export-CSV cmdlet without using a variable at all

    Get-FileMetaData $Env:userprofile\Desktop\Shell\image |select name, height,width,'horizontal resolution','vertical resolution' |
     Export-csv $Env:userprofile\Desktop\Shell\image\exportfile.csv


    Tuesday, October 27, 2015 9:48 PM