0

I wonder if there is a betterr way to write this script to gather image dimensions and filepaths. The script works great on small to medium size directories, but I'm not positive that 100,000+ files/folders is possible.

Measure-Command {

[Void][System.Reflection.Assembly]::LoadFile( "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll")

$path = "\\servername.corp.company.com\top_directory"

$data = Get-ChildItem -Recurse $path | % {
 $imageFile = [System.Drawing.Image]::FromFile($_.FullName) ;
 New-Object PSObject -Property @{
 name = $_.Name
 fullname = $_.Fullname
 width = $imageFile.Width
 height = $imageFile.Height
 length = $_.Length
 }
 }
 $data | Where-Object {$_.width -eq 500 -or $_.width -eq 250 -or $_.width -eq 1250  } |

Export-Csv \\servername.corp.company.com\top_directory\some_directory\log_file.csv -NoTypeInformation } 

I don't actually use the Where-Object filter right now.

When running the above script on a remote directory with appx. 20,000 files + folders the script takes appx. 26 minutes, before creating a .csv.

I am running the script from Powershell V2 ISE on Windows 7 and I belive the remote server is on Windows Server 2003.

Would running the script directly from the remote server be faster?

Is the process of exoprting the csv slow since all data is collected in "cache" before being written to the csv?

If all I had to go through was 20,000 files, I'd wait the 26 minutes, but 500,000 files and folders is a long wait.

I'm testing out the below method since I think my real issue is not the speed, but storing too much data in the memory. Thanks to a post from George Howarth for this, and to PoSherLife for the top script -http://powershellcommunity.org/tabid/54/aft/4844/Default.aspx

Measure-Command {
[System.Reflection.Assembly]::LoadFile( "C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll") 

"Name|SizeInBytes|Width|Height|FullName" >> C:\Users\fcool\Documents\JPGInfo.txt  

$path = "C:\Users\fcool\Documents" 
$images = Get-ChildItem -Recurse $path -Include *.jpg 

foreach ($image in $images) 
{ 
$name = $image.Name 
$length = $image.Length 
$imageFile = [System.Drawing.Image]::FromFile($image.FullName) 
$width = $imageFile.Width 
$height = $imageFile.Height
$FullName = $image.Fullname 

"$name|$length|$width|$height|$FullName" >> C:\Users\fcool\Documents\JPGInfo.txt  

$imageFile.Dispose() 
}
}

Is there any risk/loss of performance when running these scripts on non-image filetypes?

when I don't exclude non-images, I get this error:

Exception calling "FromFile" with "1" argument(s): "Out of memory." 
At C:\scripts\directory_contents_IMAGE_DIMS_ALT_method.ps1:13 char:46 
+ $imageFile = [System.Drawing.Image]::FromFile <<<< ($image.FullName) 
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException 
+ FullyQualifiedErrorId : DotNetMethodException 

thanks for any advice! and thanks again to George Howarth and to PoSherLife for the scripts!

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
fcool
  • 1
  • 1
  • 2
  • In the second function you're explicitly disposing `$imageFile`, whereas in the first function you're not. Not disposing might contribute to your memory issues since you're leaving it to the garbage collector to clean up all of those `Image` objects left hanging around. – Lance U. Matthews Mar 13 '12 at 16:04
  • I was sort of thinking that, thanks so much! – fcool Mar 14 '12 at 22:30

1 Answers1

1

Using -Filter with Get-ChildItem is much faster than -Include however you can only apply one filter string. So if you only want to match *.jpg you can use filter. In my testing using filter was close to 5 times faster than include.

Get-ChildItem -Recurse \\server\Photos -Filter *.jpg | % {
    $image = [System.Drawing.Image]::FromFile($_.FullName)
    if ($image.width -eq 500 -or $image.width -eq 250 -or $image.width -eq 1250) {
        New-Object PSObject -Property @{
            name = $_.Name
            fullname = $_.Fullname
            width = $image.Width
            height = $image.Height
            length = $_.Length
        }
    }
} | Export-Csv 'C:\log.csv' -NoTypeInformation
Andy Arismendi
  • 50,577
  • 16
  • 107
  • 124
  • 5x faster sounds good to me, thanks Andy, looking forward to testing the `-Filter` method – fcool Mar 14 '12 at 22:34