ShizukaNaHaji Posted December 10, 2012 Posted December 10, 2012 Hi All, Does anyone know if it is possible to link the Acitve Directory Thumbnail for users in to the ME Hap tile? Thanks in advance
nickbro Posted December 10, 2012 Posted December 10, 2012 It should do it automatically, as long as the user photo is stored in the jpegPhoto attribute of the user
nickbro Posted December 10, 2012 Posted December 10, 2012 Make sure the student photo handler is left blank though
reggiep Posted December 10, 2012 Posted December 10, 2012 Hi All, Does anyone know if it is possible to link the Acitve Directory Thumbnail for users in to the ME Hap tile? Thanks in advance Just out interest, why would you want to do this?
ShizukaNaHaji Posted December 10, 2012 Author Posted December 10, 2012 It should do it automatically, as long as the user photo is stored in the jpegPhoto attribute of the user Ill check that now to see if im being silly.
ShizukaNaHaji Posted December 10, 2012 Author Posted December 10, 2012 Just out interest, why would you want to do this? I am wanting the user picture to be in HAP so that it makes it a more personal experience for the users.
ShizukaNaHaji Posted December 10, 2012 Author Posted December 10, 2012 Ah ok, we set the thumbnailPhoto attribute in AD. We use this so that it shows the users picture in Outlook. Is there any way to read from that attribute? If not ill just attach the pics to the jpegPhoto. Cheers Mat
nickbro Posted December 10, 2012 Posted December 10, 2012 Hmm, odd, I've used jpegPhoto, which ms recommend, thumbnailPhoto I thought was for something else. If you know how to edit the hap source code, it's HAP.Web.LiveTiles, it's the me.cs file
ShizukaNaHaji Posted December 10, 2012 Author Posted December 10, 2012 Ill have a go. I think that Outlook 2010 only picks up the pictures from the tumbnail attribute. Ill have aplay and see what I can do. Thanks!!
reggiep Posted December 11, 2012 Posted December 11, 2012 Can anyone point to an article to tells you how to set the jpegPhoto to a students photo? I had a look on google but it seems massively complicated to me!
nickbro Posted December 11, 2012 Posted December 11, 2012 Do you know how to program? The best way I've found is to write a program to do it public void Start() { ProcessStartInfo startinfo; Process process = null; StreamReader stdoutreader; XmlDocument doc = new XmlDocument(); try { // Create a new Process Info object startinfo = new ProcessStartInfo(); // Set the Parameters for the report startinfo.FileName = @"c:\program files\sims\sims .net\CommandReporter.exe"; if (!File.Exists(startinfo.FileName)) startinfo.FileName = @"c:\Program Files (x86)\sims\sims .net\CommandReporter.exe"; string param = "EffectiveDateDate" + DateTime.Now.ToString("dd/MM/yyyy") + " 00:00:00"; startinfo.Arguments = String.Format("/USER:{0} /PASSWORD:{1} /REPORT:\"{2}\" /PARAMS:\"{3}\" /QUIET", "user", "password", "User Details Update", param); startinfo.UseShellExecute = false; startinfo.RedirectStandardOutput = true; startinfo.CreateNoWindow = true; // Start the Process process = Process.Start(startinfo); // Capture the Standard Output stdoutreader = process.StandardOutput; // Create a new XML document to hold the resilts doc = new XmlDocument(); // Load the results doc.Load(stdoutreader); process.WaitForExit(); // At this point you would do something with the results // in this case we are going to save them to a file //doc.Save(@"C:\SIMS TP Reporting SDK\Examples\ReDirectC#\obj\Debug\output.xml"); // Close down the Standard Output stream stdoutreader.Close(); stdoutreader = null; } catch { } finally { if (process != null) { process.Close(); } process = null; startinfo = null; } this.Progress = 0; DirectoryEntry usersDE = new DirectoryEntry("LDAP://DC=crick,DC=internal", "user", "password"); DirectorySearcher ds = new DirectorySearcher(usersDE); //doc.Save("c:\\temp.xml"); XmlNodeList nodes = doc.SelectNodes("/SuperStarReport/Record"); if (Initialized != null) Initialized(nodes.Count); string logpath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "error.log"); if (File.Exists(logpath)) File.Delete(logpath); foreach (XmlNode node in nodes) { if (node.SelectSingleNode("UPN") != null) { ds.Filter = "(employeeID=" + node.SelectSingleNode("UPN").InnerText + ")"; ds.PropertiesToLoad.Add("cn"); ds.PropertiesToLoad.Add("employeeID"); SearchResultCollection r = ds.FindAll(); string reg = (node.SelectSingleNode("Reg") == null ? "" : " in " + node.SelectSingleNode("Reg").InnerText); if (r.Count == 0) { ds.Filter = "(description=" + node.SelectSingleNode("Name").InnerText.Replace(" ", "\\20") + reg + ")"; r = ds.FindAll(); if (r.Count == 0) { string reg2 = reg; if (reg != "") reg2 = reg.Remove(reg.Length - 1); ds.Filter = "(description=" + node.SelectSingleNode("Name").InnerText.Replace(" ", "\\20") + reg2 + ")"; r = ds.FindAll(); if (r.Count == 0) { ds.Filter = "(description=" + node.SelectSingleNode("Name").InnerText.Replace(" ", "\\20") + ")"; r = ds.FindAll(); if (r.Count == 0) { StreamWriter sw = File.Exists(logpath) ? File.AppendText(logpath) : File.CreateText(logpath); sw.WriteLine("Error with " + node.SelectSingleNode("Name").InnerText + reg + " - Can't find in, either with UPN or with Description"); sw.Flush(); sw.Close(); continue; } } } } DirectoryEntry theUserDE = new DirectoryEntry(r[0].Path, "user", "password"); try { UpdateUser(theUserDE, node); } catch { StreamWriter sw = File.Exists(logpath) ? File.AppendText(logpath) : File.CreateText(logpath); sw.WriteLine("Error Saving " + node.SelectSingleNode("Name").InnerText + reg); sw.Flush(); sw.Close(); continue; } this.Progress++; if (Updated != null) Updated(); } } if (Done != null) Done(); } private void UpdateUser(DirectoryEntry theUserDE, XmlNode node) { //if (theUserDE.Properties["msExchQueryBaseDN"].Count == 0) theUserDE.Properties["msExchQueryBaseDN"].Add("CN=All Students,CN=All Address Lists,CN=Address Lists Container,CN=Crickhowell High School,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=crickhowell,DC=internal"); //else theUserDE.Properties["msExchQueryBaseDN"][0] = "CN=All Students,CN=All Address Lists,CN=Address Lists Container,CN=Crickhowell High School,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=crickhowell,DC=internal"; string reg = node.SelectSingleNode("Reg") == null ? "" : node.SelectSingleNode("Reg").InnerText; string[] name = node.SelectSingleNode("Name").InnerText.Split(new char[] { ' ' }); if (theUserDE.Properties["mail"].Count == 0) theUserDE.Properties["mail"].Add(string.Format("{0}@students.crickhowell-hs.powys.sch.uk", theUserDE.Properties["cn"][0].ToString().ToLower())); else theUserDE.Properties["mail"][0] = string.Format("{0}@students.crickhowell-hs.powys.sch.uk", theUserDE.Properties["cn"][0].ToString().ToLower()); if (theUserDE.Properties["employeeID"].Count == 0) theUserDE.Properties["employeeID"].Add(node.SelectSingleNode("UPN").InnerText); else theUserDE.Properties["employeeID"][0] = node.SelectSingleNode("UPN").InnerText; if (theUserDE.Properties["Department"].Count == 0) theUserDE.Properties["Department"].Add(reg); else theUserDE.Properties["Department"][0] = reg; if (theUserDE.Properties["company"].Count == 0) theUserDE.Properties["company"].Add("Crickhowell High School"); else theUserDE.Properties["company"][0] = "Crickhowell High School"; if (theUserDE.Properties["givenname"].Count == 0) theUserDE.Properties["givenname"].Add(name[0]); else theUserDE.Properties["givenname"][0] = name[0]; if (theUserDE.Properties["sn"].Count == 0) theUserDE.Properties["sn"].Add(name[name.Length - 1]); else theUserDE.Properties["sn"][0] = name[name.Length - 1]; if (theUserDE.Properties["DisplayName"].Count == 0) theUserDE.Properties["DisplayName"].Add(node.SelectSingleNode("Name").InnerText); else theUserDE.Properties["DisplayName"][0] = node.SelectSingleNode("Name").InnerText; if (theUserDE.Properties["description"].Count == 0) theUserDE.Properties["description"].Add(node.SelectSingleNode("Name").InnerText + " in " + reg); else theUserDE.Properties["description"][0] = node.SelectSingleNode("Name").InnerText + " in " + reg; if (theUserDE.Properties["employeeNumber"].Count == 0) theUserDE.Properties["employeeNumber"].Add(node.SelectSingleNode("Adno").InnerText); else theUserDE.Properties["employeeNumber"][0] = node.SelectSingleNode("Adno").InnerText; if (node.SelectSingleNode("Photo") != null) { if (theUserDE.Properties["photo"].Count == 0) theUserDE.Properties["photo"].Add(ConvertToJPEG(node.SelectSingleNode("Photo").InnerText)); else theUserDE.Properties["photo"][0] = ConvertToJPEG(node.SelectSingleNode("Photo").InnerText); theUserDE.Properties["jpegPhoto"].Clear(); theUserDE.Properties["jpegPhoto"].Add(ConvertToJPEG(node.SelectSingleNode("Photo").InnerText)); theUserDE.Properties["thumbnailPhoto"].Clear(); theUserDE.Properties["thumbnailPhoto"].Add(ConvertToJPEG(node.SelectSingleNode("Photo").InnerText)); } if (theUserDE.Properties["departmentNumber"].Count == 0) theUserDE.Properties["departmentNumber"].Add(node.SelectSingleNode("Year_x0020_taught_x0020_in_x0020_Code").InnerText); else theUserDE.Properties["departmentNumber"][0] = node.SelectSingleNode("Year_x0020_taught_x0020_in_x0020_Code").InnerText; theUserDE.CommitChanges(); } public byte[] ConvertToJPEG(string photo) { MemoryStream ms = new MemoryStream(Base64Encoder.FromBase64(photo)); Image i = Bitmap.FromStream(ms); EncoderParameters encoderParameters = new EncoderParameters(1); encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L); MemoryStream ms1 = new MemoryStream(); i.Save(ms1, GetEncoder(ImageFormat.Jpeg), encoderParameters); return ms1.ToArray(); } public static ImageCodecInfo GetEncoder(ImageFormat format) { foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageDecoders()) if (codec.FormatID == format.Guid) return codec; return null; } Attached is the SIMS report this program runs 1
nickbro Posted December 11, 2012 Posted December 11, 2012 Forgot a bit of code using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CHS.UpdateUserDetails { public class Base64Encoder { static public string ToBase64(byte[] data) { int length = data == null ? 0 : data.Length; if (length == 0) return String.Empty; int padding = length % 3; if (padding > 0) padding = 3 - padding; int blocks = (length - 1) / 3 + 1; char[] s = new char[blocks * 4]; for (int i = 0; i < blocks; i++) { bool finalBlock = i == blocks - 1; bool pad2 = false; bool pad1 = false; if (finalBlock) { pad2 = padding == 2; pad1 = padding > 0; } int index = i * 3; byte b1 = data[index]; byte b2 = pad2 ? (byte)0 : data[index + 1]; byte b3 = pad1 ? (byte)0 : data[index + 2]; byte temp1 = (byte)((b1 & 0xFC) >> 2); byte temp = (byte)((b1 & 0x03) << 4); byte temp2 = (byte)((b2 & 0xF0) >> 4); temp2 += temp; temp = (byte)((b2 & 0x0F) << 2); byte temp3 = (byte)((b3 & 0xC0) >> 6); temp3 += temp; byte temp4 = (byte)(b3 & 0x3F); index = i * 4; s[index] = SixBitToChar(temp1); s[index + 1] = SixBitToChar(temp2); s[index + 2] = pad2 ? '=' : SixBitToChar(temp3); s[index + 3] = pad1 ? '=' : SixBitToChar(temp4); } return new string(s); } static private char SixBitToChar(byte b) { char c; if (b < 26) { c = (char)((int)b + (int)'A'); } else if (b < 52) { c = (char)((int)b - 26 + (int)'a'); } else if (b < 62) { c = (char)((int)b - 52 + (int)'0'); } else if (b == 62) { c = s_CharPlusSign; } else { c = s_CharSlash; } return c; } static public byte[] FromBase64(string s) { int length = s == null ? 0 : s.Length; if (length == 0) return new byte[0]; int padding = 0; if (length > 2 && s[length - 2] == '=') padding = 2; else if (length > 1 && s[length - 1] == '=') padding = 1; int blocks = (length - 1) / 4 + 1; int bytes = blocks * 3; byte[] data = new byte[bytes - padding]; for (int i = 0; i < blocks; i++) { bool finalBlock = i == blocks - 1; bool pad2 = false; bool pad1 = false; if (finalBlock) { pad2 = padding == 2; pad1 = padding > 0; } int index = i * 4; byte temp1 = CharToSixBit(s[index]); byte temp2 = CharToSixBit(s[index + 1]); byte temp3 = CharToSixBit(s[index + 2]); byte temp4 = CharToSixBit(s[index + 3]); byte b = (byte)(temp1 << 2); byte b1 = (byte)((temp2 & 0x30) >> 4); b1 += b; b = (byte)((temp2 & 0x0F) << 4); byte b2 = (byte)((temp3 & 0x3C) >> 2); b2 += b; b = (byte)((temp3 & 0x03) << 6); byte b3 = temp4; b3 += b; index = i * 3; data[index] = b1; if (!pad2) data[index + 1] = b2; if (!pad1) data[index + 2] = b3; } return data; } static private byte CharToSixBit(char c) { byte b; if (c >= 'A' && c <= 'Z') { b = (byte)((int)c - (int)'A'); } else if (c >= 'a' && c <= 'z') { b = (byte)((int)c - (int)'a' + 26); } else if (c >= '0' && c <= '9') { b = (byte)((int)c - (int)'0' + 52); } else if (c == s_CharPlusSign) { b = (byte)62; } else { b = (byte)63; } return b; } static private char s_CharPlusSign = '+'; /// /// Gets or sets the plus sign character. /// Default is '+'. /// static public char CharPlusSign { get { return s_CharPlusSign; } set { s_CharPlusSign = value; } } static private char s_CharSlash = '/'; /// /// Gets or sets the slash character. /// Default is '/'. /// static public char CharSlash { get { return s_CharSlash; } set { s_CharSlash = value; } } } } 1
ShizukaNaHaji Posted December 11, 2012 Author Posted December 11, 2012 Can anyone point to an article to tells you how to set the jpegPhoto to a students photo? I had a look on google but it seems massively complicated to me! There is a tool called AD Photo edit free if you want to just do a few: Cjwdev | AD Photo Edit
mattgrimley Posted December 11, 2012 Posted December 11, 2012 Ill have a go. I think that Outlook 2010 only picks up the pictures from the thumbnail attribute. Ill have a play and see what I can do. Thanks!! That's in line with what i have found too. Outlook (the only real reason for doing it) seems to use the wrong attribute - but there's little point in sticking to our principles when - Our network management software (BCX Management Tools) allows us to set it for Outlook purposes (and to make managing users a bit prettier) - but we stick that in the thumbnail attribute so it shows up in Outlook. (mine is in both from when i was experimenting with it - but im hesitant to put it in both, it seems like a lot of extra data to go into the AD...
ShizukaNaHaji Posted December 11, 2012 Author Posted December 11, 2012 (mine is in both from when i was experimenting with it - but im hesitant to put it in both, it seems like a lot of extra data to go into the AD... I find that if I put it in both attributes it oddly disappears from Outlook and you end up with the little silhouette. I did have a look at the HAP source code but I think its a bit beyond me
nickbro Posted December 11, 2012 Posted December 11, 2012 Ok, I'll make a change to HAP+ to use the thumbnailPhoto instead
nickbro Posted December 11, 2012 Posted December 11, 2012 (edited) Ok, just released the update for this: v8.5.1211.1240 is out on the v8.5 release. Ok, it should be on codeplex, it's attached if needed as it looks like codeplex is down atm Edited December 11, 2012 by nickbro
ShizukaNaHaji Posted December 11, 2012 Author Posted December 11, 2012 Fantastic! Ill give it a go now!
nickbro Posted December 11, 2012 Posted December 11, 2012 Make sure the studentPhotoHandler is set to nothing though
ShizukaNaHaji Posted December 11, 2012 Author Posted December 11, 2012 Nick, Eeek, what do you mean by studentPhotoHandler? I think I'm being a little dense. Mat
ShizukaNaHaji Posted December 11, 2012 Author Posted December 11, 2012 Hi Nick, I have checked and there is nothing in the studentPhotoHandler. However its still not picking up the pics? I dropped the dll files into the bin directory on the HAP server but still no joy. Any ideas? Its prob something I’m doing wrong! !
joyer99 Posted December 11, 2012 Posted December 11, 2012 Nick, Not to piggyback on another problem (and if you want to move it to another thread, that's fine) , I was curious about this feature as well and added a user's picture into Active Directory. I only added it in for one staff member to test it out. If I go into attribute editor under that user's properties, I can see that it is set. But when I log-in to HAP+ as that user, I get the generic user picture. I didn't know if there was something that I was missing. I did check out the videos on the hap.codeplex site, but the videos were for older versions of HAP+ and talked about SIMS. I setup a test site called HAPTEST with a fresh install, thinking maybe it was some configuration on the actual site that I had screwed up, and it still didn't show up on the fresh install. I looked at the photo handler line in hapconfig.xml and it is set as follows: "photohandler="" />". Looking at the source code of the page it says the following: Test Teacher (testteacher) Edit Profile Logout Is there something else that I have to configure for it to pull the Active Directory Photo? Thanks!
nickbro Posted December 11, 2012 Posted December 11, 2012 can you try going to /hap/api/mypic, it may be getting cached
joyer99 Posted December 11, 2012 Posted December 11, 2012 Nick, When I go to /hap/api/mypic I get the following: HAP/api/tiles/icons/128/128/images/icons/metro/folders-os/UserNo-Frame.png. If I select the picture, I can see the generic user photo. Thanks!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now