4

I am using following powershell (that I got from here http://spsatheesh.wordpress.com/2011/06/03/download-all-the-profile-pictures-through-powershell-using-web-service/)so I can download all the profile pictures. The script runs and displays index number and the profile id (with domain) on the screen. however, profile pictures are not saved.

= = = script = = =

[system.reflection.assembly]::LoadWithPartialName("System.IO")
[system.reflection.assembly]::LoadWithPartialName("System.Web")


$SUrl       = 'https://yourcompany.com/_vti_bin/userprofileservice.asmx?wsdl'
$filename   = 'report.csv'



function Download()
{
    trap [Exception]
       {
        Write-Output "-------------------------------Error"     
         Write-Output $_.Exception.Message
         Write-Output "-------------------------------Error"
         continue
       }

        $datel = Get-Date
        Write-Output "INFO: `t $datel `t Job Started"

        Write-Host "Set Path to Store Pictures"  
        $FilePath = Read-Host

        if($FilePath.EndsWith("\") -eq $false)
        {
          $FilePath = $FilePath + "\"
        }

        Write-Host "Enter the User Profile Web Service Url"
        $SUrl = Read-Host

        Write-Host "Enter the User name & Password using which it needs to connect the service"
        #Create Credential Object
        $Credential = Get-Credential

        #Get Service
        #$Service = New-WebServiceProxy -Uri $SUrl -NameSpace UserProfileService -UseDefaultCredential
        $Service = New-WebServiceProxy -Uri $SUrl -NameSpace UserProfileService -Credential $Credential


        #Create WebRequest
        $WebRequest = new-object System.Net.WebClient
        #$WebRequest.Credentials = [System.Net.CredentialCache]::DefaultCredentials
        #$WebRequest.Credentials = new-object System.Net.NetworkCredential("palnisam","password","domain")
        $WebRequest.Credentials =  $Credential.GetNetworkCredential()


        #[IO.Directory]::SetCurrentDirectory((Convert-Path (Get-Location -PSProvider FileSystem)))
        #$Reader = new-object System.IO.StreamReader($filename)

        $ProfileCount = $Service.GetUserProfileCount()
        $ProfileLoop  = 0;
        $NextIndex = 358;
        for($ProfileLoop = 0;$ProfileLoop -le $ProfileCount;$ProfileLoop++)
        {
            trap [Exception]
            {
            }

            $UPD = $Service.GetUserProfileByIndex($NextIndex)
            $AccountName = $UPD.UserProfile[1].Values[0].Value
            $PictureURL = $UPD.UserProfile[20].Values[0].Value
            if($PictureURL -ne $null)
            {
              $FileName = $FilePath +$AccountName.SubString($AccountName.LastIndexOf("\")+1) + $PictureUrl.SubString($PictureUrl.LastIndexOf("."))
              $WebRequest.DownloadFile($PictureUrl,$FileName)
            }

            $NextIndex = $UPD.NextValue
            Write-Host "$ProfileLoop ----- $AccountName"
        }

}
  • This is really a powershell question not a SharePoint question, but are you certain that $PictureURL is even being populated? – Dave Wise Feb 15 '12 at 21:55
  • Is there a reason you are using the User Profile Web Service rather than the SharePoint API? When I run your code I don't get values in PictureUrl, I suspect it is because you are hardcoding the index at 20. – Matthew McDermott Feb 15 '12 at 22:24
3

OK, I got your code working for me. You should change the property getter to look like the following, I left in the original lines for reference:

#$AccountName = $UPD.UserProfile[1].Values[0].Value 
$Prop = $UPD.UserProfile | Where-Object { $_.Name -eq "AccountName" } 
$AccountName = $Prop.Values[0].Value

#$PictureURL = $UPD.UserProfile[20].Values[0].Value 
$Prop = $UPD.UserProfile | Where-Object { $_.Name -eq "PictureURL" } 
$PictureURL = $Prop.Values[0].Value

I am sure there is a better way in PowerShell, but this should work for you.

1

You can download UserProfie pictures from SharePoint 2010 on-premise environment using CSOM code

using Microsoft.Office.Server.UserProfiles;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.UserProfiles;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace ExportUserPictureCSOM
{
class Program
{
static void Main(string[] args)
{

XmlDocument doc = new XmlDocument();
doc.Load("InputXml.xml");
string siteUrl = string.Empty;
string password = string.Empty;
string exportImageLocation = string.Empty;
string inputCSVLocation = string.Empty;
string logfileName = string.Empty;
string loginName=string.Empty;         
XmlNodeList root = doc.SelectNodes("Element/InputDetails");
if (root == null)
{
Console.WriteLine("Error Reading Input File");
return;
}

foreach (XmlNode input in root)
{
siteUrl = input["siteUrl"].InnerText;
exportImageLocation = input["ExportImageLocation"].InnerText;
inputCSVLocation = input["InputCSVFullPath"].InnerText;
loginName = input["loginName"].InnerText;

}

if (siteUrl == string.Empty || exportImageLocation == string.Empty || inputCSVLocation == string.Empty || loginName == string.Empty || password == string.Empty)
{
Console.WriteLine("Missing Mandatory Input parameter");
return;
}


ClientContext clientContext = new ClientContext(siteUrl);
FormsAuthenticationLoginInfo credentials = new FormsAuthenticationLoginInfo(loginName, password);
//  clientContext.Credentials = credentials;
clientContext.AuthenticationMode = ClientAuthenticationMode.FormsAuthentication;
clientContext.FormsAuthenticationLoginInfo = credentials;
Microsoft.SharePoint.Client.Web site = clientContext.Web;
clientContext.Load(site);
clientContext.ExecuteQuery();
Console.WriteLine("Title: {0}", site.Title);
var reader = new StreamReader(System.IO.File.OpenRead(inputCSVLocation));
int count = 0;
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
count++;
if (count > 1) //Start from Second Line
{

string email = getEmailID(line);

string userID = line.Split(',')[0].Replace("\"", "");
string firstName = line.Split(',')[1].Replace("\"", "");
string surName = line.Split(',')[2].Replace("\"", "");
email = "i:0#.f|infocentre|" + email;
try
{

var user = site.EnsureUser(email);

string pictureUrl = null;
clientContext.Load(user);
clientContext.ExecuteQuery();

string newfileName = firstName + "_" +  surName + "_" + userID + ".jpg";
newfileName = Regex.Replace(newfileName, @"[#/?:,*""><~]+", "", RegexOptions.Compiled);
newfileName = exportImageLocation + @"\" + newfileName;

string fileUrl = getImageUrl(email, clientContext, site);

if (fileUrl != null)
{

    Uri destFileName = new Uri(fileUrl);
    string server = destFileName.AbsoluteUri.Replace(destFileName.AbsolutePath, "");
    string serverrelative = destFileName.AbsolutePath;
    Microsoft.SharePoint.Client.FileInformation f = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, serverrelative);


    using (var fileStream = new FileStream(newfileName, FileMode.Create))
    {
        f.Stream.CopyTo(fileStream);
    }
}
else
{

    Console.WriteLine("User Image not found:" + email);

}
}
catch (Exception ex)
{
Console.WriteLine("Error getting User Details :" + email);

}
}
}



Console.ReadKey(true);
Console.WriteLine();
}

private static string getImageUrl(string userAccount, ClientContext clientContext, Web site)
{


var user = site.EnsureUser(userAccount);

string pictureUrl = null;
clientContext.Load(user);
clientContext.ExecuteQuery();


int userId = user.Id;
CamlQuery query = new CamlQuery();

query.ViewXml = "<View><Query><Where><Eq><FieldRef Name='ID' />" +
"<Value Type='Integer'>" + userId + "</Value>" +
"</Eq></Where></Query><ViewFields><FieldRef Name='Picture'/>" +
"</ViewFields></View>";

ListItemCollection items = clientContext.Web.SiteUserInfoList.GetItems(query);

clientContext.Load(items);
clientContext.ExecuteQuery();

foreach (ListItem item in items)
{
FieldUrlValue picture = (FieldUrlValue)item["Picture"];
if (picture != null)
{
//Console.WriteLine(picture.Url);
pictureUrl = picture.Url;
}
}


return pictureUrl;
}

private static string getEmailID(string line)
{
string[] userValues = line.Split(',');
string email = string.Empty;

foreach (var item in userValues)
{
if (item.Contains('@'))
{
email = item.Replace("\"", "");
break;
}
}
return email;
}
}
}

Two input files:

  1. CSV file contains list of users and Email ids(csvInput.csv)
  2. Xml input file contains input parameters(InputXml.xml)

CSV File format:

User ID,First Name,Surname,E-mail,
1233,veera,induvasi,veera@abc.com,
1333,mahesh,gupta,mg@abc.com,
2345,abc,azx,abc@abc.com,

More detail: http://veerainduvasi.blogspot.co.uk/2016/10/download-sharepoint-userprofile-picture.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.