Adding Pictures to Active Directory and Show in SharePoint 2013

Adding Pictures to Active Directory and Show in SharePoint 2013

A very common setup request for SharePoint is for it to pull pictures of employees directly from Active Directory. This allows all employee photos to be managed in a central location, and give some governance to how the photos should look.

This post will take you through adding images into Active Directory and having SharePoint display it.

 

Adding Photos into Active Directory

Adding Photos into Active Directory is not as simple as opening up Active Directory Users and Computers, choosing the employee and uploading a photo. Active Directory stores photos as a bytes, so when adding images to Active Directory, you have to pass it in as bytes. Not a big challenge using PowerShell.

The following command will upload the Harvey_Brent.jpg photo into active directory for the user bharvey. I’ve ran this on the AD server.

$userName = “bharvey”
$filePath = “c:\temp\Harvey_Brent.jpg”
[byte[]]$img = Get-Content $filePath –encoding byte
Get-ADUser –filter {samaccountname –eq $userName} |
Set-ADUser –replace @{thumbnailphoto=$img}

Now, if you look into the bharvey AD user, you can see the thumbailphoto attribute is set with a list of hex values which make up the photo’s bytes.

 

Setting up Photos in SharePoint 2013

To set up SharePoint to use these photos, our first step will be to map the SharePoint “Picture” column to the Active Directory “thumbnailPhoto” column. We can do this from within the User Profile Service Application. While in the “Manage Profile Service” page, within Central Administration, click on the “Manage User Properties” link.

 

On the “Manage User Properties” page, find the “Picture” property and go into the Picture property’s edit page. This is where you will configure the mapping, as well as set other settings, e.g. if users should be able to change the image themselves. For the mapping, select thumbnailPhoto, and Import, and click the “Add”.

Publishing Photos to SharePoint 2013

Now that we have the photos in Active Directory and the mapping configured. All we need to do is run an incremental Profile Synchronization from the same “Manage Profile Service” page to get the photo(s) we’ve added into Active Directory. Then, we will just need to run another PowerShell command to make sure that the SharePoint profile photo store is compatible with SharePoint Server 2013. (This will need to be run by a user with AD edit rights).

We also specify the MySites Host site, where the images will be stored.

$mySitesUrl = “http://my.bharveyserver”
$mySitesHost = Get-SPSite –Identity $mySitesUrl
Update-SPProfilePhotoStore –MySiteHostLocation $mySitesHost
–CreateThumbnailsForImportedPhotos $true

With that, all the images that we’ve added to Active Directory are now available in SharePoint.

Working with Multiple Virtual Machines in Hyper-V

As a consultant who works on many different projects, it is always a good idea to keep projects separate.  The best way to keep things separate is to create multiple virtual machines.  This can pose a few problems, like the time it takes to build a virtual machine and get it fully configured.  And all that hard drive space just to have multiple virtual machines with the same software installed.  In the long run, the benefits of multiple virtual machines out-weigh these costs.  You not only get to archive out-dated projects, freeing up valuable/precious hard drive space, but you do not cross contaminate your projects.  We’ve all said this: “it works on my machine“.  Well there is a reason for that.  Maybe you changed a setting in the registry, or modified some permissions while working on another project on the same virtual machine.  “I know I did something with the registry, but I can’t remember what.”

Using multiple virtual machines solves that issue, but what about your time and space?  If you haven’t solved the Einstein-Rosen bridge, you should try using differencing drives to alleviate some of the wasted time and space. 

A differencing disk is a virtual disk which points to a “parent” virtual disk. So when you create a virtual machine with a differencing drive, you are starting with a baseline image (parent) and any changes made in the virtual machine are saved to a separate virtual disk (child). Any subsequent virtual machine you create with a differencing drive, you can also point to the “parent,” since it remains unchanged. This saves space, since anything stored on the “parent” virtual disk is shared between the children. Using differencing disks also saves time since you don’t need to install a new operating system, any security updates, or any commonly used software. You just point to the baseline image and go. 

Create Parent Image

  1. Create a new virtual machine using Hyper-V manager. 
    • Install your operating system, the software you will share from VM to VM, and all the security updates they entail.
  2. Run the SysPrep.exe utility.   
    • SysPrep /oobe /generalize /shutdown
  3. Remove the virtual machine from Hyper-V Manager.  (You don’t need to run this directly anymore).
  4. Make the .VHD/.VHDX file read-only.  This is important!  Any change to the base image will render virtual machines created off of it invalid.

Create Virtual Machines

  1. Create a new virtual machine using Hyper-V Manager but choose the “attach a virtual hard disk later” option.
  2. Right click the newly created virtual machine and go into the “Settings…”
  3. Click on the IDE Controller 0 and click to add a new hard drive. 
  4. Click the “New” button to create a new drive and select the “Differencing” disk type
    • Choose the parent disk that you created before.
  5. Start the machine, enter in the product code and start developing.

With that you have just saved your future self some time, since creating new virtual machines will take no time at all. No need to copy an already existing SysPrep-ed image. No need to copy anything! All you need to do is point to a disk that already exists.

In addition, you can create a differencing disk which points to a differencing disk.  So if you have projects which use different technologies, like SharePoint and BizTalk, you can start by creating a base image with just the operating system on it.  Then, you can create two disks, one for SharePoint and one for BizTalk, which both point to the baseline operating system image.  Then, when creating a new virtual machine, you can just point to either the SharePoint disk or BizTalk disk, both of which also share the same disk.

5 Minute JQuery Image Slider

The image slider, such a common need and yet sometimes so hard to find. There are tons of good sliders out there made with JQuery. Some are hard to use, others aren’t. Some can only do a portion of what you need while others are so massive they are hard to customize. With this post I intend to show you, in under 50 lines of code (HTML, JS and CSS) how to build a simple slider that you can use on your projects. The code can easily be extended with JavaScript/JQuery, and through simple CSS can be customized to fit a div or go full screen (as this example shows as this was my need). This is the five minute image slider! Comments have been included in the code to explain what’s going on.

The images provided are not owned by me but rather are the result of a quick image search on Bing. These should be swapped out for your own images. In addition…

This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Tested in IE9, IE 10, but should work in most/all modern browsers.

 

<!DOCTYPE html>
<head>
	<script src="http://code.jquery.com/jquery-1.9.0.js" type="text/javascript"></script>
	<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js" type="text/javascript"></script>
	<style type="text/css">
		body {
			margin:0; /* remove the default margin */
			padding:0; /* remove the default padding */
		}

		#slides, #slides img.active{
			min-height: 100%; /* important; sets the hight in this case full screen */
			min-width: 1024px; /* a minimum width set to a standard screen size */
			width: 100%; /* important; sets to full screen */
			height: auto; /* this just sets a full height */
			position: fixed; /* tells it to not move */
			top: 0; /* top corner */
			left: 0; /* left side */
			display:block; /* display as a block element */
		}

		#slides img {
			display:none; /* normal images are hidden */
		}
	</style>
	<script type="text/javascript">
		function slide(div) {
			var $active = $('#' + div + ' .active'); // we add this class to images that are going to show
			var $next = ($('#' + div + ' .active').next().length > 0) ? $('#' + div + ' .active').next() : $('#' + div + ' img:first'); // get the next image
			$next.fadeIn("slow").addClass('active'); // set the class on the next image
			$active.fadeOut(function () { // a pretty little function which removes the class from the currently active image
				$active.removeClass('active'); // remove .active
			});
		}
		$(document).ready(function () { // where the magic happens
			setInterval('slide("slides")', 5000); // swap the image at X interval
		});
	</script>
</head>
<body>
<div id="slides"> <!-- notice I put the div name as a param in the slide() function -->
	<img src="http://www.onlinegames.cat/wp-content/uploads/2011/11/halo-4-1.jpg" class="active" alt="" />
	<img src="http://hdfreewallpapers.com/walls/2012/07/13/gears_of_war_4-HD.jpg" alt="" />
</div>
</body>
</html>

 

Enjoy!

Securing Large Data Models in Master Data Services 2012

I ran into this issue today when experimenting with the security capabilities in SQL Server 2012 Master Data Services.  I am working with a very large Product data model for a Manufacturing client.  The core entity has 391 attributes at this point in time.  I was attempting to understand how I can secure this entity such that users responsible for mass updating a set of attributes can refine their view only to  those attributes.

In the prior version of MDS (SQL Server 2008 R2), Attribute Groups were the solution to this problem. In 2012, it would seem that Attribute Groups are not secured in the same way. But that is a topic for another time.

When I attempted to set a Deny permission on a single attribute in the model, I received a generic error in the Web Application interface: An Unknown Error has occurred. When I turned on the Trace in web.config (located under C:\Program Files\SQL Server\110\Master Data Services\WebApplication), saw the following error:

MDS Error: 0 : LogError : Operation is not valid due to the current state of the object.
    DateTime=2013-01-18T16:46:19.5107689Z

StackOverflow to the rescue!  This error is apparently a common one in ASP.NET web applications where large collections are being serialized.  By adding an appSettings key to the web.config, I was able to increase the limit of collection keys/members:

<appSettings> <add key=”aspnet:MaxHttpCollectionKeys” value=”2001″ /> </appSettings>

http://stackoverflow.com/questions/8832470/operation-is-not-valid-due-to-the-current-state-of-the-object-error-during-pos

And that solved the problem!