Posts

Uploading pictures into ActiveDirectory remotely via PowerShell

One can upload pictures into PowerShell remotely. A few requirements:
1. Install RSAT; ; that’s adding the Feature in Computer Management
2. Have remote web services running on AD
3. Have sufficient access; you must be member of either the Organization Management or Recipient Management role groups to upload the pictures.
4. Have a set of photos, preferably named with the user accounts, JPGs, 96×96 and less than 10kb

Here’s what’s needed in PowerShell to get started using AD CmdLets:

Import-module ActiveDirectory
if ((Get-PSSnapin -Name ActiveDirectory -ErrorAction SilentlyContinue) -eq $null ){
import-module ActiveDirectory
}

here’s how to see the existing picture for a given user:

$user = Get-ADUser [user] -Properties thumbnailphoto
$user.thumbnailphoto.length
$user.thumbnailphoto | Set-Content "C:tempJtest3a.jpg" -Encoding byte -Force

Testing in Outlook: Pictures are cached in Outlook for the duration of the session. To check whether the picture is available, one has to totally exit Outlook.

Let’s get all the files to process:

$LocalFiles = get-childitem -Path $WorkingPath -filter $TypeFilter | where {!$_.PSIsContainer} 

To upload the picture, get the user:

$User = Get-ADUser -Filter {SamAccountName -eq $Name}

Let’s get the photo after resizing to 96×96 ensuring it is less than 10k

$Photo = [byte[]](Get-Content "$WorkingPath$File" -Encoding byte)
Set-ADUser $Name -Replace @{thumbnailPhoto=$Photo}

AD User group membership not propagating into site collections

AD User group membership propagation issue

In some rare instances, users may exist within a Site Collection that don’t receive their AD group membership updates.

I’ve traced this down to recreated AD users that have the same account name, yet a new SID. The solution is to wipe the user references from the site collection.

Be forewarned, any user permissions will be wiped as well. One more excellent reason to only use AD groups for assigning permissions in SharePoint!

You can see this internal list and even delete the user by adapting this URL:
http ://WebApp/ManagedPath/namedSiteCollection/_layouts/people.aspx?MembershipGroupId=0

Better to do it in PowerShell for speed, extensibility, consistency, and across many site collections. The trick comes down to a specific way to eliminate the user from the site collection:

$RootWeb.SiteUsers.Remove($MyUser)

Note trying $RootWeb.Users.Remove($MyUser) or $RootWeb.AllUsers.Remove($MyUser) will not work.

To finish it off, I prefer to re-add the user:

$RootWeb.EnsureUser($MyUser)

Here’s the full script, where I traverse through site collections in a Web App, filter them based on criteria (in this case the managed path), then carefully take the action on a list of users (one or more, comma separated), and output any failures along the way:

Start-SPAssignment –Global
$UsersToWipe = "DOMAINPoorBloke"
$UsersToWipeArray = $UsersToWipe.Split(“,”)
$siteUrl = "http ://sharepoint"  
Write-Host "script starting $(get-date)" 
$rootSite = New-Object Microsoft.SharePoint.SPSite($siteUrl)
$spWebApp = $rootSite.WebApplication 
foreach($site in $spWebApp.Sites)
{
if ($site.Url -notlike "$siteurl/SpecificPath/*") 
{
Write-Host "Fast Skipping $($site.Url)"
}
else
{ 
$rootWeb = $site.RootWeb;
foreach ($MyUser in $UsersToWipeArray)
{
try
{
try
{
$user1 = $RootWeb.EnsureUser($MyUser)
}
catch
{
Write-Host "x1: Failed to ensure user $($MyUser) in $($Site.url)"
}
try
{
$RootWeb.SiteUsers.Remove($MyUser)
$RootWeb.update()
}
catch
{
Write-Host "x2: Failed to remove $($MyUser) from all users in $($Site.url)"
}
try
{
$user1 = $RootWeb.EnsureUser($MyUser)
}
catch
{
Write-Host "x3: Failed to ensure user $($MyUser) in $($Site.url)"
}
}
catch
{
Write-Host "x4: other failure for $($MyUser) in $($Site.url)"
}
}
} #Site to process 
$site.Dispose();  
} #foreach Site
Write-Host "script finishing $(get-date)" 
Stop-SPAssignment –Global