Window Support Software

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Thursday, 13 December 2012

Interact Intranet: Automate the Extraction of Binary Profile Pictures for use in Active Directory

Posted on 13:18 by Unknown
Active Directory can be used as a central repository for the storage of profile pictures.  This source can then feed email, CRM, intranets, messaging and other enterprise software.

Unfortunately, there isn't an out of the box way for users to add these photos directly to Active Directory (as far as I'm aware!) so some trickery needs to happen to get this all to work.

This blog post will explain how we extract user profile pictures from our Interact Intranet environment and then upload them to Active Directory.


Step 1: SQL query to identify users and their pictures

Microsoft recommends square profile pictures with dimensions of 96x96.  Interact conveniently already thumbnails pictures into preset sizes.  After testing, we found that their 4th size, 75px width, has sufficient clarity when used in Active Directory, which allows us to export pictures without the need for programatic image manipulation.  Note: If you do want to investigate image manipulation you might start with a library like ImageMagick.
select PERSON.NTUsername, ASSET_INSTANCE.BinaryData
from PERSON
INNER JOIN ASSET_INSTANCE
on PERSON.AssetID=ASSET_INSTANCE.AssetID
Where PERSON.NTUsername != 'ARCHIVED'
and PERSON.AssetID is not NULL
and AssetSize='4' 

Step 2: Export pictures to a file path

Below is the code that is triggered though a nightly job to extract the binary data from the database and convert it into files at the designed path.
Credit for this code, and pulling this project together, comes from coding ninja extraordinaire Matt Chiste from Integryst who was able to complete the development in less time than it took me to write the requirements!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using System.IO;
namespace PicExporter
{
    class Program
    {
        static string connString = "Data Source=<redacted>;Initial Catalog=<redacted>;Persist Security Info=True;User ID=<redacted>;Password=<redacted>";
        static string cmdString = "select PERSON.NTUsername, ASSET_INSTANCE.BinaryData from PERSON INNER JOIN ASSET_INSTANCE on PERSON.AssetID=ASSET_INSTANCE.AssetID Where PERSON.NTUsername != 'ARCHIVED' and PERSON.AssetID is not NULL and AssetSize='4'";
        static string folder = "pics/";
        static string FILENAME_EXTENSION = ".jpg";
        static int FILENAME_INDEX = 0;
        static int BINARY_INDEX = 1;
        static string PROP_FILE = "picexporter.properties";
        static void Main(string[] args)
        {
            Console.Out.WriteLine("START: " + DateTime.Now.ToString());
            // vars
            string filename;
            loadVars();
            // set up the connection
            SqlConnection conn = new SqlConnection(connString);
            SqlCommand cmd = new SqlCommand();
            SqlDataReader rdr=null;
            try
            {
                // run the command
                conn.Open();
                cmd.Connection = conn;
                cmd.Parameters.Clear();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = cmdString;
                rdr = cmd.ExecuteReader();
                // iterate the users
                while (rdr.Read())
                {
                    // write to the log
                    Console.Out.Write("Extracting user: " + rdr[FILENAME_INDEX].ToString());
                    // get the byte array for the image
                    Byte[] b = new Byte[(rdr.GetBytes(BINARY_INDEX, 0, null, 0, int.MaxValue))];
                    rdr.GetBytes(BINARY_INDEX, 0, b, 0, b.Length);
                    // write rest of line to the log
                    Console.Out.Write(" (" + b.Length + "bytes)");
                    // check existing file
                    filename = folder + rdr[FILENAME_INDEX].ToString() + FILENAME_EXTENSION;
                    if (File.Exists(filename))
                        Console.Out.Write(" [UPDATE]" + Environment.NewLine);
                    else
                        Console.Out.Write(" [NEW]" + Environment.NewLine);
                    // user names prefixed with the domain will have a \ in them.  Need to make sure the full folder path is created
                    if (!Directory.Exists(Path.GetDirectoryName(filename)))
                    {
                        Console.WriteLine("Creating Folder: " + Path.GetDirectoryName(filename));
                        Directory.CreateDirectory(Path.GetDirectoryName(filename));
                    }
                    // write the file
                    FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
                    fs.Write(b, 0, b.Length);
                    fs.Close();
                }
            }
            catch (Exception ex)
            {
                Console.Out.WriteLine("EXCEPTION: " + ex.Message);
                Console.Error.WriteLine("EXCEPTION: " + ex.Message);
            }
            finally {
                // close the connections
                if (rdr != null)
                    rdr.Close();
                if (conn != null)
                    conn.Close();
            }
            Console.Out.WriteLine("FINISH: " + DateTime.Now.ToString());
        }
        static void loadVars()
        {
            string propFile = Directory.GetCurrentDirectory() + "\\" + PROP_FILE;
            string line, name, value;
            StreamReader file = null;
            // Read the file line by line
            try
            {
                file = new System.IO.StreamReader(propFile);
                while ((line = file.ReadLine()) != null)
                {
                    try
                    {
                        name = (line.Substring(0, line.IndexOf('=')));
                        value = (line.Substring(line.IndexOf('=')+1));
                        if (name == "connString")
                            connString = value;
                        else if (name == "cmdString")
                            cmdString = value;
                        else if (name == "folder")
                        {
                            folder = value;
                            if (!Directory.Exists(folder))
                            {
                                Console.WriteLine("Creating Folder: " + folder);
                                Directory.CreateDirectory(folder);
                            }
                        }
//                        else
//                            Console.WriteLine("ignoring property: name: " + name + ", val: " + value);
                    }
                    catch (Exception)
                    {
                        // ignore line without "="
//                        Console.WriteLine("ignoring line: " + line);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Out.WriteLine("ERROR READING " + propFile + ": " + ex.Message);
                Console.Error.WriteLine("ERROR READING " + propFile + ": " + ex.Message);
            }
            finally
            {
                if (file != null)
                    file.Close();
            }
        }
    }
}
Reference: http://support.microsoft.com/kb/317016

Step 3: Import pictures to Active Directory

The following powershell script runs through a scheduled job.  The job searches the folder we have extracted photos to for newly modified photos and then calls the script, which matches the filename of the photo to the network User Name and then uses native Active Directory APIs to add the image to the user’s profile.
param($Identity,$Path);
# Import a .jpg into Active Directory for use as the Exchange/Outlook GAL Photo
# For best resultsL <10kb files, 96x96 dimensions
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin
if (!$Identity)
{
    throw "Identity Missing";
}
if (!$Path)
{
    throw "Path Missing";
}
if (!(Get-Command Get-User))
{
    throw "Exchange Management Shell not loaded";
}
$User = Get-User $Identity -ErrorAction SilentlyContinue
if (!$User)
{
    throw "User $($Identity) not found";
}
if (!(Test-Path -Path $Path))
{
    throw "File $($Path) not found";
}
$FileData = [Byte[]]$(Get-Content -Path $Path -Encoding Byte -ReadCount 0);
if($FileData.Count -gt 10240)
{
    throw "File size must be less than 10K";
}
$adsiUser = [ADSI]"LDAP://$($User.OriginatingServer)/$($User.DistinguishedName)";
$adsiUser.Put("thumbnailPhoto",$FileData);
$adsiUser.SetInfo()

Email ThisBlogThis!Share to XShare to FacebookShare to Pinterest
Posted in Active Directory, AD, binary, Interact-Intranet, SQL | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • Deleting AutoComplete Entries In Outlook
    Your Outlook is not just a mere email client; it is a very efficient personal manager tool. MS Outlook can help you take notes, make journal...
  • Interact Intranet: Automate the Extraction of Binary Profile Pictures for use in Active Directory
    Active Directory can be used as a central repository for the storage of profile pictures.  This source can then feed email, CRM, intranets, ...
  • How to Set Password on Your Windows XP
    Windows XP is the most popular operating system in the world. It has got a number of unique features, which make it a favourite to all. It w...
  • Configure Windows Live Or Hotmail Account In Your IPhone
    IPhone lets you configure your email accounts in it, and now, if you have a Hotmail account, we will give you tips on how to configure that ...
  • Steps To Set Up The Email Filter In Outlook
    As we all know, Microsoft Outlook contains some of the most advanced and novel features which help users to remember and organize their impo...
  • Walk-through of domain configuration for Oracle WebCenter 11g: on Windows Server 2008 x64 & MS SQL 2008
    In my previous post I covered the third step of the "simple" installation topology, Install other Fusion Middleware products , and...
  • How To Tackle The Buffer Overflow Situation
    Normally a program runs on a sufficient amount of memory. However, when the program consumes more memory than required, a phenomenon called ...
  • Oracle WebCenter Interaction: Using multiple logins and URLs to access your portal
    When we purchased Plumtree licenses way back in the day we had visions of using the software to run our intranet and as an extranet for smal...
  • Walk-through of post install tasks for Oracle WebCenter: on Windows Server 2008 x64 & MS SQL 2008
    In my previous post I covered the fourth step of the "simple" installation topology, Configure domain for WebCenter , and will now...
  • Excel Tips & Tricks
    I enjoy spreadsheets and working with numbers.  A lot of this joy comes from the satisfaction of being able to keep track of many different ...

Categories

  • 64bit
  • access a help link
  • Active Directory
  • AD
  • Adaptive Layouts
  • Administrator account
  • Antimalware programs
  • binary
  • collaboration
  • content management
  • content migration
  • CSS
  • Data Connection
  • Data execution prevention
  • Ease your work
  • Eclipse
  • Email accounts
  • Email in Outlook
  • End process
  • Excel
  • hosting
  • iCalendar
  • ics
  • IIS
  • install
  • Interact-Intranet
  • Intranet
  • Jive Express
  • Jive SBS
  • Jive Software
  • Knowledge Directory
  • Liferay
  • Liferay Developer Studio
  • Linux
  • Local Computer Policy
  • login
  • Microsoft chat
  • Microsoft Help
  • Microsoft support
  • Microsoft tech support
  • Microsoft word application
  • Minimum hardware requirements
  • Mozilla Firefox web browser
  • MS SQL 2008
  • New Mail Notification
  • Oracle
  • Oracle ECM
  • Oracle Enterprise Content Management
  • Oracle OpenWorld
  • Oracle WebCenter
  • Oracle WebCenter Analytics
  • Oracle WebCenter Analytics 10.3.0.1
  • Oracle WebCenter Interaction
  • Oracle WebCenter Suite
  • Outlook 2007
  • Outlook Express Address Book
  • Outlook Repair
  • Outlook repair utility
  • Outlook settings
  • Outlook support
  • Outlook tech support
  • Password protection
  • Plumtree
  • portals
  • Programs and Features
  • Publisher
  • RCU
  • redirect
  • Remove AVG toolbar
  • Remove malwares
  • Screen Scraping
  • Search
  • set password
  • SharePoint
  • SQL
  • SQL Server Reporting Services
  • Studio
  • Task manager
  • try Windows 8
  • Underline feature
  • vanity URL
  • Vista problems
  • WCI
  • WebCenter Interaction
  • WebCenter Suite
  • WebLogic Server
  • Windows 7 Support
  • Windows 8 Support
  • Windows 8 transfer
  • Windows Blue
  • Windows Easy Transfer tool
  • Windows live chat support
  • Windows Live Photo Gallery
  • Windows Online Support
  • Windows Server 2008
  • Windows support
  • Windows Vista help
  • Windows XP support
  • WLS
  • Xbox 360 controller

Blog Archive

  • ►  2013 (33)
    • ►  December (1)
    • ►  November (1)
    • ►  October (8)
    • ►  August (2)
    • ►  July (4)
    • ►  June (4)
    • ►  May (3)
    • ►  April (2)
    • ►  March (2)
    • ►  February (1)
    • ►  January (5)
  • ▼  2012 (32)
    • ▼  December (4)
      • Install The GIF Support On To Your Windows Machine
      • Interact Intranet: Automate the Extraction of Bina...
      • How to Set Password on Your Windows XP
      • Hide Content Based Upon Iframe Parent
    • ►  November (5)
    • ►  October (2)
    • ►  September (7)
    • ►  August (1)
    • ►  July (1)
    • ►  June (8)
    • ►  May (2)
    • ►  April (1)
    • ►  March (1)
  • ►  2011 (30)
    • ►  November (3)
    • ►  October (2)
    • ►  September (2)
    • ►  August (4)
    • ►  July (3)
    • ►  June (5)
    • ►  May (4)
    • ►  April (2)
    • ►  March (3)
    • ►  January (2)
  • ►  2010 (8)
    • ►  December (2)
    • ►  November (1)
    • ►  October (5)
Powered by Blogger.

About Me

Unknown
View my complete profile