Importer vos photos de profils en lot dans SharePoint 2013

ProfilSharePointVide     ftline_line_arrow_end    ProfilSharePoint

Scénario :

Vous avez un grand nombre d’employés dans votre entreprise et vous voulez leur simplifier la tâche en important leur photo de profil en lot. Vous avez au préalable obtenu leur consentement et vous êtes chargé d’effectuer cette opération!

Prérequis :

  • Vous disposez d’un environnement « On-premises » et avez accès au compte de la ferme.
  • Les noms de photos suivent la nomenclature suivante : NomDomaine_NomUtilisateur.jpg
    • Généralement ce n’est pas le cas, alors je vous suggère de les renommer avec un script PowerShell.

Solution :

  • Créer une application console nommé « ProfilUtilisateur.ImporterPhoto » en C# .Net dans un environnement SharePoint de développement.
  • Copier le code suivant dans le fichier Program.cs (Version modifié du blog « My Share Points ») :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Reflection;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Portal.WebControls;
using System.IO;
using Microsoft.Office.Server.UserProfiles;

namespace ProfilUtilisateur.ImporterPhoto
{
    /// <summary>
    /// Sources :
    /// http://lixuan0125.wordpress.com/2013/04/08/upload-user-profile-pictures-programmatically-sharepoint-2013/
    /// http://pholpar.wordpress.com/2010/03/10/how-to-upload-a-user-profile-photo-programmatically/
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            Program prog = new Program();

            Console.Write(@"Profile images path (Ex : C:\photo) : ");
            string profileImagesPath = Console.ReadLine(); //E.g : "C:\\photo"

            Console.Write("MySite URL (Ex : http://monsite/) : ");
            string mySiteUrl = Console.ReadLine(); //E.g : "http://monsite/"

            prog.UploadProfileImages(profileImagesPath, mySiteUrl);
        }

        private void UploadProfileImages(string path, string urlMySite)
        {
            using (SPSite site = new SPSite(urlMySite))
            {
                SPServiceContext serverContext = SPServiceContext.GetContext(site);
                UserProfileManager userProfileManager = new UserProfileManager(serverContext);

                using (SPWeb web = site.OpenWeb())
                {
                    SPFolder subfolderForPictures = web.Folders["User Photos"].SubFolders["Images du profil"];
                    // Get all image files in a folder
			  //The name of the images folder may be different depending on the language of your SharePoint installation.

                    DirectoryInfo dir = new DirectoryInfo(path);
                    FileInfo[] Images = dir.GetFiles();
                    foreach (FileInfo img in Images)
                    {
                        string imageFilePath = path + "\\" + img.Name;

                        string fileName = Path.GetFileNameWithoutExtension(img.Name);
                        string accountName = fileName.Replace("_", "\\");

                        // if User Profile exists then upload the images
                        if (userProfileManager.UserExists(accountName))
                        {
                            UploadPhoto(accountName, imageFilePath, subfolderForPictures);
                            SetPictureUrl(accountName, subfolderForPictures, userProfileManager.GetUserProfile(accountName));
                        }
                       // else
                        //{ Console.WriteLine("User {0} does not exist.", accountName); }
                    } // end of loop
                }
            }
        } // end of function

        private void UploadPhoto(string accountName, string imageFilePath, SPFolder subfolderForPictures)
        {
            if (!File.Exists(imageFilePath) || Path.GetExtension(imageFilePath).Equals(".gif"))
            {
                Console.WriteLine("File '{0}' does not exist or has invalid extension", imageFilePath);
            }
            else
            {
                string fileNameWithoutExtension = GetFileNameFromAccountName(accountName);

                FileStream file = File.Open(imageFilePath, FileMode.Open);
                BinaryReader reader = new BinaryReader(file);

                if (subfolderForPictures != null)
                {
                    // try casting length (long) to int
                    byte[] buffer = reader.ReadBytes((int)file.Length);

                    int largeThumbnailSize = 300;
                    int mediumThumbnailSize = 72;
                    int smallThumbnailSize = 48;

                    using (MemoryStream stream = new MemoryStream(buffer))
                    {
                        using (Bitmap bitmap = new Bitmap(stream, true))
                        {
                            CreateThumbnail(bitmap, largeThumbnailSize, largeThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_LThumb.jpg");
                            CreateThumbnail(bitmap, mediumThumbnailSize, mediumThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_MThumb.jpg");
                            CreateThumbnail(bitmap, smallThumbnailSize, smallThumbnailSize, subfolderForPictures, fileNameWithoutExtension + "_SThumb.jpg");
                        }
                    }
                }
                Console.WriteLine("Uploading image '{0}' for user '{1}'", imageFilePath, accountName);
            }
        } // end of function

        /// Get sealed function to generate new thumbernails
        public SPFile CreateThumbnail(Bitmap original, int idealWidth, int idealHeight, SPFolder folder, string fileName)
        {
            SPFile file = null;

            Assembly userProfilesAssembly = typeof(UserProfile).Assembly;

            Type userProfilePhotosType = userProfilesAssembly.GetType("Microsoft.Office.Server.UserProfiles.UserProfilePhotos");
            MethodInfo[] mi_methods = userProfilePhotosType.GetMethods(BindingFlags.NonPublic | BindingFlags.Static);

            MethodInfo mi_CreateThumbnail = mi_methods[0];
            if (mi_CreateThumbnail != null)
            {
                file = (SPFile)mi_CreateThumbnail.Invoke(null, new object[] { original, idealWidth, idealHeight, folder, fileName, null });
            }

            return file;
        } // end of function

        /// Update User Profile Property
        private void SetPictureUrl(string accountName, SPFolder subfolderForPictures, UserProfile userProfile)
        {
            accountName = accountName.Replace("\\", "_");

            string account = accountName.Substring(0, accountName.IndexOf("_")) + "\\" + accountName.Substring(accountName.IndexOf("_") + 1);

            string pictureUrl = String.Format("{0}/{1}/{2}_MThumb.jpg", subfolderForPictures.ParentWeb.Site.Url, subfolderForPictures.Url, accountName);

            userProfile["PictureUrl"].Value = pictureUrl;
            userProfile.Commit();
        } // end of function

        private string GetFileNameFromAccountName(string accountName)
        {
            string result = accountName;
            string charsToReplace = @"\/:*?""<>|";
            Array.ForEach(charsToReplace.ToCharArray(), charToReplace => result = result.Replace(charToReplace, '_'));
            return result;
        }
    }
}
  • Ouvrir une fenêtre de commande DOS en tant que l’administrateur de la ferme et glisser-déplacer le fichier « ProfilUtilisateur.ImporterPhoto.exe » généré préalablement.
    • Appuyé sur la touche « Entrer »
    • Saisir le chemin du dossier contenant vos photo Ex : C:\photo
    • Saisir le chemin vers votre site MySite Ex : http://<monsite&gt;
  • Naviguer vers le dossier des photos SharePoint Ex : http://<monsite>/Users photos/ pour constater que toute les photos ont été importées et que les miniatures ont été générées avec succès.

Dans mon prochain billet nous verrons comment il est possible de synchroniser ces photos importées dans SharePoint vers Lync, l’Active directory ainsi que dans votre profil Windows!

Le code source d’origine provient du site : http://lixuan0125.wordpress.com/

Advertisements

Cas d’étude: Les assurances Royer Delisle

Les Assurances Royer Delisle est une société autonome en assurance de dommages, un franchisé de la Capitale assurance générales. Depuis quelques années, cette entreprise domine le marché tant au niveau de l’assurance des particuliers que des entreprises.  Oeuvrant dans un secteur de plus en plus compétitif ou les marges sont minimes, les Assurances Royer Delisle ont dû retravailler leur façon de faire pour d’accroitre leur efficacité opérationnelle, quantifier la qualité des différents liens d’ affaires, améliorer la gestion et communication interne. Tout cela dans le but de pouvoir se concentrer davantage sur leur mission, la croissance du volume d’affaire.

DELISLE_L_ROYER_S_BEAULIEU_V

Dans ce contexte, les assurances Royer Delisle ont fait appel au groupe Metalogique afin de mettre sur pied un partenariat visant à trouver les paramètres de l’équation suivante « Travailler mieux = Travailler plus efficacement supporté par de meilleures outils ». Ainsi, les membres de Metalogique se sont mis à pied d’oeuvre pour revoir le processus de gestion de l’information avec les dirigeants de l’entreprise. Il nous a fallu prendre en compte certains éléments qui commandaient un investissement de temps considérable pour la direction :
  •    Gestion du temps des employés et horaires de travail
  •    Suivi des ventes dans un intervalle de temps précis par employé et par type de produit vendu
  •    Identifier des ratios de ventes par secteur d’activité , par produit , par contact d’affaire, etc.
  •    Réassignation d’un dossier à une ressource
  •    Diffusion de l’information interne de toute sorte
Suite aux ateliers, nous avons développé sous SharePoint une application qui permet de fixer des objectifs mensuels communs pour les équipes de ventes et d’afficher visuellement l’évolution de celles-ci via un thermomètre de rendement, adjoint à cela un système simplifié de gestion du temps des employés fut mis en place permettant ainsi aux ressources de pouvoir gérer leur temps adéquatement afin de pouvoir prendre quelques heures de congé lors des moments moins sollicités.
Ventes
Concernant le volet gestion ; les gestionnaires ont des outils leur permettant de produire des rapports sur les ventes et sur les commissions, tant par employés que par région ou produit. Ces données sont ensuite exploitées par Powerview où des tableaux de gestion basés sur des données géomatiques sont produits.
Note.: Le graphique ci-bas est un exemple avec des données et valeurs fictives, en vue de protéger la confidentialité des données »
ExPowerView
Nous avons démarré un projet pilote qui a rapidement permis à l’entreprise de rencontrer ses objectifs d’affaires, en plus de constater des gains à des niveaux inattendus  :
  • Comptabilisation de chaque lien d’affaires d’affaires, produit.
  • Identification des opérations rentables vs celles qui le sont moins
  • Planification stratégique sur le développement et la mise en marché
  • Fixation d’objectifs de ventes réalistes basés sur des chiffres réels
  • Meilleure structure dans le classement des documents et de l’actif organisationnel
  • Meilleure communication entre les membres de l’équipe
Aux dires de madame Beaulieu, membre du CA de l’organisation:

Metalogique a su comprendre tous nos besoins rapidement et nous emmener des points de vue très utiles pour nous aider à performer davantage en utilisant adéquatement les bonnes solutions d’affaires pour chaque situation.  Il nous ont permis notamment d’avoir une meilleure vision pour l’atteinte de nos objectifs de ventes. Sans cet outil de travail, il nous aurait été difficile de croire qu’il est réaliste de planifier une croissance de 28% pour l’an prochain. Grâce à eux,  nous savons où concentrer nos efforts et notre rendement collectif s’en voit grandement amélioré.

Monsieur Delisle, membre du CA de l’organisation:

Le portail préparé par l’équipe de Métalogique nous permet en quelques secondes de répondre à une foule de questions à savoir par exemple  si dans une région donnée, pour un type de produit précis, notre  ratio de  vente est bon.  Nous pouvons avec cet outil planifier notre positionnement stratégique et quelques mois plus tard facilement quantifier les actions posées et se réajuster en fonction des résultats.
Merci Métalogique

Pour contacter Les assurances Royer & Delisle :
1 866 432-2049

Metalogique accompagne les entreprises et les organisations dans leur évolution TI.
Imaginez demain, réalisez-le aujourd’hui avec nous !
En savoir plus sur nos solutions.

Masquer facilement le menu de gauche dans SharePoint

Nombreux sont ceux qui m’ont fait part du besoin de retirer la navigation de gauche dans certaines pages de leur portail SharePoint.

En fait, la recette est toute simple ! Il suffit d’insérer l’extrait de code suivant soit dans un « Script Editor WebPart », soit en l’intégrant directement dans un « Page Layout » ou « MasterPage ».

<style type= »text/css »>
#sideNavBox { display : none;}
</style>
Amusez-vous bien 🙂

L’accès restreint aux ressources informationnelles

Sans titreLe sujet de ce billet m’est venu après que nous ayons dû modifier le premier URL de ce blogue, car son accès était bloqué dans plusieurs ministères et organismes gouvernementaux. Le coupable: la présence dans l’adresse du mot « blog ».

N’est-il pas intéressant de constater qu’encore aujourd’hui, de nombreuses entreprises et organisations ont des politiques restrictives vis-à-vis l’utilisation de l’internet? D’autant que les raisons qu’on nous sert pour se justifier relèvent bien souvent d’arguments qui tenaient la route… il y a dix ans !

Ainsi, on bloque  l’accès à une mine d’informations en limitant l’utilisateur aux seuls applications et sites jugés (par qui ?) pertinents à leur travail. On limite l’accès, outre certains blogues, à des applications sociales ou de partage, surtout si elles sont hébergées dans l’infonuagique.

Pourtant, jour après jour, les sources d’information et de savoir se multiplient et se diversifient. Les occasions de s’autoformer et de se perfectionner sont légions. On prive donc les employés d’un accès à des ressources susceptibles de supporter, voire accroître leurs connaissances et contribuer ainsi tant à leur satisfaction au travail qu’à leur rendement.

Laissez-moi vous partager quelques points qui font qu’un environnement limité et appauvri, tel qu’on le connaît actuellement à plusieurs endroits, n’a plus sa place :

  1. Aujourd’hui être pris à l’intérieur des murs de son organisation constitue un SILO en soi, puisque la terre entière ne demande qu’à partager des connaissances via l’internet. S’en priver, s’est s’isoler et évoluer en vase clos.
  2. Les gens ont désormais la possibilité de se munir de leur propre appareil mobile et peuvent aisément naviguer sur les sites de leur choix et ce, sans égard aux politiques de l’organisation qui les emploie.
    1. Ce phénomène engendre le BYOD (Bring your Own Device). Ainsi, les employés se dotent eux-mêmes de leurs propres outils et il devient difficile d’implanter un standard de mobilité pour l’organisation puisque tout est disparate (Android/iOS/Windows Phone). Cela complique singulièrement l’éventuel déploiement d’une stratégie mobile.
  3. Enfin, la grande majorité des personnes ont acquis une maturité dans leur utilisation (judicieuse) d’internet et il n’est plus vrai que de libérer les accès serait source de distraction et d’abus. Le contraire sera l’exception, et il s’agit là d’un enjeu de gestion davantage que de sécurité informatique.

Dans ce contexte, l’intranet nouveau devrait contenir non seulement les contenus internes, mais aussi libérer et encourager l’accès à des sites externes. Il devrait être un lieu de convergence où l’employé pourra trouver le résultat mis à jour en temps réel des trouvailles et suggestions de ses pairs et partager les siennes. Histoire de se garder à jour dans son domaine d’expertise, d’élargir son regard, d’étoffer ses positions.

Changement de philosophie pour plusieurs, certes, et gros bon sens pour les plus visionnaires.