# Export-SPPhoto # # Downloads SharePoint Profile Images into a directory # #Requires -version 3 param ( [string]$spusername = "" , # username to login at sharepoint. leave emmtry to use default credentials [string]$sppassword = "" , # provide password, if not using default credentials [string]$spServer = "https://intranet.msxfaq.de", # Rest URL to profile photos #[string]$spRESTurl = "/_api/web/GetFolderByServerRelativeUrl('/User Photos/Profile Pictures')/Files", # Rest URL to profile photos [string]$spRESTurl = "/_api/web/GetFolderByServerRelativeUrl('/User Photos/Profilbilder')/Files", # Rest URL to profile photos [string]$imagepath = "C:\Export-SPPhoto\images\", # directory to store the images [string]$lastrunfile = "C:\Export-SPPhoto\logs\Export-SPPhoto.lastrun", [string]$lockfilename = "C:\Export-SPPhoto\logs\Export-SPPhoto.lock", [string]$logdirectory = "C:\Export-SPPhoto\logs" ) set-psdebug -strict write-host "Export-SPPhoto: Start" $error.Clear() $starttime = get-date [int]$exitcode=0 write-host "Export-SPPhoto: Transcript" if (!(test-path $logdirectory -PathType Container)) { mkdir $logdirectory } if (!(test-path $imagepath -PathType Container)) { mkdir $imagepath } [string]$Transcriptfile = (".\logs\Export-SPPhoto."+(get-date -format "yyyy-MM-dd-HH-mm-ss-fff")+".log") Start-Transcript -path $Transcriptfile write-host "Prevent multiple instances with a lock file" try { "Lockfile" | out-file -filepath $lockfilename $lockfile = [System.IO.File]::Open($lockfilename , 'Open', 'Read', 'None') write-output ("Log: PurgeOldLogs:LOCKFile:Successful") } catch { write-output ("Log: PurgeOldLogs:LOCKFile is not lockable - assume parallel process. stopping") $lockfile = $null Stop-Transcript exit 1 } $error.clear() write-output ("Log: PurgeOldLogs:Purging old Logs") try { get-item -path "$($logdirectory)\Export-SPPhoto*.log" ` | where-Object {$_.lastwritetime -lt ((get-date).adddays(-30))} ` | ForEach-Object{ remove-item -path $_.fullname -ErrorAction silentlycontinue -ErrorVariable removeitemerror if ($removeitemerror) { write-output ("Log: Unable to Remove" + $_.fullname) $Error.Remove($error[$Error.Count-1]) } } } catch { write-output ("Log: Eror during Transcript file cleanup") } write-host "Prepare Summary variable" $result = New-Object PSObject -Property @{ totalphotos = [long]0 totalnew = [long]0 totalunchanged = [long]0 totalremoved = [long]0 totalfaileddownload = [long]0 } write-host "------------------------------------------------" write-host "Prepare SharePoint REST Call" write-host " SPServer $($spServer)" write-host " RestURL $($spRESTurl)" $Headers= @{ "accept" = "application/json;odata=verbose" } $spRESTResults= $null write-host " Loading List of Photos in SharePoint from URL" Write-host " $($spServer+$spRESTurl)" if ($spusername -eq "") { write-host " Calling with default credentials" $spRESTResults=Invoke-RestMethod -Uri ($spServer+$spRESTurl) -UseDefaultCredentials -Method GET -Headers $Headers } else { write-host " Calling with credentials for User $($spusername)" $spSecPassword=ConvertTo-SecureString $sppassword -AsPlainText -Force $spCredentials = New-Object System.Management.Automation.PSCredential($spusername, $spSecPassword) $spRESTResults=Invoke-RestMethod -Uri ($spServer+$spRESTurl) -Credential $spCredentials -Method GET -Headers $Headers } if (!$spRESTResults) { write-host "No results found - Check RestURL, certificate and credentials" [int]$exitcode=1 } else { $totalpictures = $spRESTResults.d.results.Count write-host " Total Files found: $($totalpictures)" [hashtable]$picturelist= @{} write-host "------------------------------------------------" write-host "Processing Pictures" [long]$count=0 foreach ($entry in ($spRESTResults.d.results)){ write-host "Processing $($entry.name)" -nonewline $Count++ Write-Progress ` -Activity "Read and Import UserPhoto " ` -PercentComplete ($count/$totalpictures*100) ` -CurrentOperation "Processing ($($count)/$($totalpictures) Entry:$($entry.name)" ` -Status "Runtime $(((get-date) - $starttime).totalseconds) Seconds" if ($entry.name.endswith("_LThumb.jpg")) { write-host " Found LargeFile" $result.totalphotos++ $picturelist[$entry.name]=$true [string]$imagefilepath = ($imagepath + $entry.name) [string]$pictureURL = $entry.__metadata.id +'/$value' [datetime]$splastmod = [datetime]$entry.TimeLastModified [datetime]$filelastmod = [datetime]"1.1.1900" if (test-path -path $imagefilepath -pathtype leaf) { write-host " Loading LastMod from local file" $filelastmod = (get-item $imagefilepath).LastWriteTime } if ($splastmod -gt $filelastmod) { write-host "SharePoint is newer -Downloading" -nonewline [boolean]$newimage=$false try{ Invoke-RestMethod ` -Uri $pictureURL ` -UseDefaultCredentials ` -Method GET ` -Headers $Headers ` -Outfile $imagefilepath ` -erroraction silentlycontinue [boolean]$newimage=$true } catch { Write-host" Unable to Download current Image" -backgroundcolor red $result.totalfaileddownload++ } if ($newimage) { write-host " Download OK" -foregroundcolor green $samaccoutname = $entry.name.replace("_LThumb.jpg","") write-host " User Name $($samaccoutname)" } } else { write-host " File not newer - Skip" $result.totalunchanged++ } } else { write-host " Skip NonLarge File" } } Write-host "Start search for removed images" $filelist = get-childitem $imagepath Write-host "Total Files to Check $($filelist.count)" [long]$count=0 foreach ($file in $filelist) { $count++ Write-Progress ` -Activity "Search for removed files" ` -PercentComplete ($count/$($filelist.count)*100) ` -CurrentOperation "Processing ($($count)/$(($filelist.count)) File:$($File.name)" ` -Status "Runtime $(((get-date) - $starttime).totalseconds) Seconds" Write-Host " RemoveCheck $($file.name) " -nonewline if ($picturelist[$file.name]) { write-host " File valid" } else { write-host " File removed in SharePoint." -backgroundcolor yellow $result.totalremoved++ remove-item $file.fullname } } } Write-host "Summary" Write-host " Total totalphotos $($result.totalphotos)" Write-host " Total totalnew $($result.totalnew)" Write-host " Total totalunchanged $($result.totalunchanged)" Write-host " Total totalremoved $($result.totalremoved)" Write-host " Total totalfaileddownload $($result.totalfaileddownload)" write-Host ("Log: Release lockfile") $lockfile.close() remove-item -path $lockfile.name write-host "Export-SPPhoto: End with Exitcode $($exitcode)" Write-host "TotalSeconds $(((get-date) - $starttime).totalseconds)" Stop-Transcript exit $exitcode