SharePoint 2013

[SP2013] – implémenter un JSLink dans les Annonces – Afficher le contrôle Like

Posted on Updated on

Bonjour à tous,

Cette fois-ci je vais vous parler d’une personnalisation de SharePoint 2013 au travers des JSLink. Ces JSLink sont apparus avec SharePoint 2013 et permettent de personnaliser les affichages des données à plusieurs niveaux grâce à ce que l’on appelle le Client-Side Rendering (CSR). Vous pourrez ainsi personnaliser :

  • Les Vues (List View)
  • Les Formulaires (dispform, editform)
  • Les champs (SPFields)

Il s’agit donc ici de contrôler la manière dont ces différents éléments seront rendus dans les pages SharePoint à l’aide de JavaScript principalement. Je ne serai volontairement pas exhaustif dans cet article car il me faudrait beaucoup de temps et cela me laissera peut-être l’opportunité d’écrire de nouveaux articles.

Voici donc mon périmètre : proposer un bouton Like/Unlike dans le formulaire d’affichage d’une actualité (Dispform de la liste Announcements (TemplateID = 104) et ceci sans recourir au déploiement d’une solution SharePoint WSP, mais en réalisant les opérations seulement coté “client”, avec des droits Administrateur de site (pas de ferme).

L’idée est donc de produire et déployer un fichier JavaScript dans SharePoint et de l’utiliser en l’associant à mon formulaire Dispform, sans perdre de fonctionnalités natives ou brider le comportement de ma liste, formulaires etc.

 

1/ Activer le Like sur la liste d’Announcements (Annonces)

Rien de très compliqué ici. La plupart des administrateurs fonctionnels ou techniques de sites SharePoint sauront réaliser l’opération. Pour cela, il faut naviguer jusqu’à la liste en question, et aller dans ses Paramètres. Dans cette page, nous allons dans le menu Paramètres d’évaluation (Rating Settings) :

01

Puis d’autoriser les évaluations de type “Like” :

  1. Autoriser les éléments à être évalués (traduction approximative…) : Oui
  2. Quel type d’évaluation : Likes

02

Et bien sûr, nous validons la page avec le bouton “OK”.

 

2/ Activer le JSLink sur le formulaire Dispform de la liste Announcements

En effet, une phase de préparation est nécessaire. Les formulaires (Dispform, Editform) ne proposent pas directement le paramètres JSLink sur le composant WebPart positionné dans ces pages. C’est bien ce composant WebPart qui est chargé d’afficher le formulaire avec ses champs (entêtes et contrôles de rendu).

Pour cela, il faut se rendre dans les paramètres du site > MasterPage Gallery (dans la catégorie Web Designer Galleries) :

03

Pour ma part, je choisis de placer mon JSLink dans le sous-dossier Display Templates mais il est préférable de les placer dans un sous-dossier afin de s’y retrouver à l’avenir…

Ensuite, on Upload un fichier JavaScript presque vide (SharePoint n’accepte pas de télécharger des fichiers vides…), ici appelé “jsnewsdispform.js” :

04

05

On clique sur “OK” pour valider et on renseigne le formulaire suivant. Ici il faudra être précis !

  • Choisir le Content Type : JavaScript Display Template
  • Name : Nom du fichier JavaScript (conservez celui indiqué)
  • Title : Au choix
  • Target Control Type : Form
  • Standalone : Override
  • Target Scope : Url du site où se situe l’Application Announcements (l’url de mon site en l’occurence)
  • Target List Template ID : 104 (Template ID pour les Annonces SharePoint)

 

06

07

On valide en cliquant sur “Save”. Le fichier est enregistré (il faudra penser à le publier en version principale si la gestion des versions est activée) :

08

Copier l’url du document jsnewsdispform.js (url absolue dans un fichier texte, cela nous resservira plus tard).

3/ Modification du Dispform.aspx et ajout du lien vers le fichier JavaScript

Le prérequis sont en place, il nous faut maintenant indiquer au formulaire Dispform.aspx de notre liste d’annonces qu’il doit utiliser l’attribut JSLink… et bien sûr le faire pointer vers notre fichier JavaScript.

Pour cela, naviguez vers l’Application d’annonce créé sur votre site. Si aucune actualité n’est présente, créez en une qui nous servira pour aller sur la page Dispform.aspx.

09

Une fois fait, cliquez sur une actualité. La page s’ouvre, c’est bien la page Dispform.aspx.

10

Puis on passe en mode Edition sur la page. Pour cela, utilisez le menu Site Settings (Paramètres du site) et cliquez sur “Edit page” (Editer la page) :

11

La page se rafraichit, elle est en mode Modification. Dans le coin haut-droit du WebPart, cliquez sur “Edit Web Part” :

12

La boite à outil (Toolbox) du WebPart s’affiche. Dans la catégorie “Miscellaneous” (Divers de mémoire…), le champ JSLink est bien disponible (si vous n’avez pas réalisé les étapes précédentes, il ne sera pas disponible).

Dans ce champ JSLink, entrez (en modifiant l’url si besoin, suivant l’emplacement du fichier jsnewsdispform.js) :

~site/_layouts/15/reputation.js|~site/_catalogs/masterpage/Display%20Templates/jsnewsdispform.js

13

Notez l’emploi de “|” pour demander à SharePoint de charger plusieurs fichiers JavaScript. Et ici nous aurons besoin à la fois du fichier jsnewsdispform.js mais également reputation.js pour gérer les Likes/Unlike.

Validez en cliquant sur “OK” et sauvegardez la page :

14

A partir de ce moment, lorsque que la page dispform sera affichée, notre fichier sera chargé.

4/Implémentation du JSLink

Nous abordons ici l’aspect le plus complexe. Comme je l’ai dit au début de l’article, je ne vais pas détailler l’usage du JSLink, mais je peux déjà vous conseiller la lecture de l’article proposé par Tobias Zimmergren (et l’ensemble de ses excellents articles) ici : http://zimmergren.net/technical/sp-2013-using-the-spfield-jslink-property-to-change-the-way-your-field-is-rendered-in-sharepoint-2013 et également la série d’articles de Martin Hatch ici : http://www.martinhatch.com/2013/08/jslink-and-display-templates-part-1.html.

Ensuite, quelques précisions. L’implémentation JavaScript peut être complexe, et dans l’exemple présent, le code est loin d’être parfait et vous demandera forcément une phase d’optimisation, de refactorisation afin de l’adapter pour de la production. Une fois mes excuses présentées aux grands chefs du JavaScript, voici mon exemple qui fonctionne !

4.1 Charger les éléments nécessaires

Effectivement, pour faire fonctionner la plupart des JSLink il est bon de se documenter et de bien connaitre les Features proposées par SharePoint 2013. En particuler le MDS (Minimal Download Strategy) qui aura un impact fort sur tous vos développements JSLink. Je ne vais pas détailler non plus le pourquoi du comment, il y a des dizaines d’article qui traitent du sujet (Cf. Google & compagnie, en particulier l’article de Wictor Wilén : http://www.wictorwilen.se/the-correct-way-to-execute-javascript-functions-in-sharepoint-2013-mds-enabled-sites).

Pour pouvoir fonctionner avec et sans la fonctionnalité MDS activée, voici ce que l’on peut écrire :


//Load CSR-MDS module if feature is activated
if (typeof _spPageContextInfo != "undefined" && _spPageContextInfo != null) {
    RegisterInMDS();
}
else {
    RegisterLikes();
}

//Register CSR-MDS module then call template registration
function RegisterInMDS() {
    // MDS enabled site
    RegisterModuleInit(_spPageContextInfo.siteServerRelativeUrl + "/_catalogs/masterpage/Display%20Templates/jsnewsdispform.js", RegisterLikes);
    // MDS disabled site
    RegisterLikes();
}

4.2 Afficher les contrôles

Puis on appelle la fonction RegisterLikes() qui se charge d’indiquer qu’un nouveau Template de rendu est associé au champ “LikesCount”, pour le formulaire DisplayForm. J’ajoute également une ligne qui permettra de charger JQuery que j’utiliserai dans ma solution (s’il n’est pas déjà présent).
Je demande donc ici d’appeler la fonction LikeFieldViewTemplate lorsque le champ LikesCount est appelé dans un formulaire de type Dispform :


//Register Template for Number Of Like Field
function RegisterLikes () {

   // Loading jQuery from a CDN path if the local is unavailable
   (window.jQuery || document.write("< script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.0.min.js">< /script>"));
   var likeFieldCtx = {};

   likeFieldCtx.Templates = {};   
   likeFieldCtx.Templates.Fields = {"LikesCount": {
	"DisplayForm": LikeFieldViewTemplate
   }};

   SPClientTemplates.TemplateManager.RegisterTemplateOverrides(likeFieldCtx);
}

NB : j’aurai également dû, et c’est la bonne pratique, déclarer un namespace pour rassembler mes fonctions.

Puis on déclare la fonction qui se chargera du rendu :


//Display Number Of Like field with custom format
function LikeFieldViewTemplate(ctx) { 
	
   var likeFieldcontext = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);
	
   ExecuteOrDelayUntilScriptLoaded(function() { GetItemData(ctx, ctx.FormContext, likeFieldcontext.fieldName); },"sp.js");
	
}

Ici je récupère le contexte associé au formulaire courant. Vous trouverez sur le net plusieurs façon de réaliser cela, mais dans le contexte du Dispform, c’est la seule qui a fonctionné pour moi : utiliser SPClientTemplates.Utility.GetFormContextForCurrentField(ctx). Ensuite j’appelle la fonction GetItemData mais après que sp.js soit chargé (ExecuteOrDelayUntilScriptLoaded).

Cette fonction GetItemData permet de charger le contexte dont j’aurai besoin, en particulier les Fields qui ne sont pas affichés dans le formulaire (de manière générale, s’ils ne sont pas affichés, ils ne sont pas chargé). Hors j’ai besoin du champ “LikedBy” pour afficher le nom des personnes qui ont déjà liké cet élément.

On charge donc ici l’item (colonnes : LikedBy, ID, LikesCount et Title) et pour cela on utilise la fonction load() et executeQueryAsync() en JSOM à partir de l’ID de l’item :


function GetItemData(ctx, formContext, likeFieldName) {

   var itemId = formContext.itemAttributes.Id;
   var listId = formContext.listAttributes.Id;

   var clientContext = SP.ClientContext.get_current();
   var list = clientContext.get_web().get_lists().getById(listId);
   clientContext.load(list, 'Title', 'Id');
   var item = list.getItemById(itemId);
   clientContext.load(item, "LikedBy", "ID", "LikesCount", "Title");
   clientContext.executeQueryAsync(
      Function.createDelegate(this, 
            function(){onLoadItemDataSucceeded(item, listId, ctx, likeFieldName);}),
            Function.createDelegate(this, onLoadItemDataFailed));
}

La fonction “onLoadItemDataSucceeded()” appelée en cas de succès du chargement de l’item permet d’afficher les contrôles : smiley + bouton Like/Unlike dans la page. Ce bouton appellera une fonction JavaScript personnalisée qui se chargera d’appeler l’API sociale de SharePoint.
On stocke le html nécessaire dans une variable htmlresult. Cet HTML sera injecté grâce à JQuery dans la page.

Dans ce premier extrait de la fonction onLoadItemDataSucceeded, le but est de récupérer le nom de toutes les personnes ayant liké l’élément avec une limite imposée à 5 noms et de placer “You” en début de liste si l’utilisateur connecté l’a déjà liké. Par ailleurs on peut arriver à 6 noms si l’utilisateur connecté arrive en dernier. Mais pour moi, cela n’est pas un problème. Le fait d’indiquer que l’utilisateur connecté a déjà liké prévaut sur le nombre de “likers”.



function onLoadItemDataSucceeded(item, listId, ctx, likeFieldName) {
   var likesCount = item.get_item('LikesCount');
   var itemId = item.get_item('ID')
   var likedBy = null;
   var likers = [];
   var likerslist = '';
   var userAlreadyLike = false;
   var currentUserId = _spPageContextInfo.userId;
   var linkerslimit = 5;
   var linkerslimitOverpass = false;
	
   var htmlresult = "";
	
   //Get likes & likers on current item
   if(likesCount != 0) {
      var likedBy = item.get_item("LikedBy");
		
      if (!SP.ScriptHelpers.isNullOrUndefined(likedBy)) {
	
         for(var i=0; i < likedBy.length; i++) {
            likers[likers.length] = {
               id: String(likedBy[i].get_lookupId())
               , title: likedBy[i].get_lookupValue()
            };
            //If user in loop is current user, then display You on first row of the tooltip
            if(likers[i].id == currentUserId) {
               userAlreadyLike = true;
               likerslist = 'You' + likerslist;
            }	
            else if(i < linkerslimit){				
               likerslist += likers[i].title + "\\r";				
         }
         else linkerslimitOverpass = true;
      }
      if(linkerslimitOverpass == true) {
         //If limit of likers is overpass, then display "..." at the end of the tooltip
         likerslist += '...';
      }
   }
   else {
      likesCount = 0;
   }
}
else {
   likesCount = 0;
}   

Ce second extrait construit le HTML et l’injecte via JQuery. Le but ici est de modifier l’entête de la colonne qui est “Number of likes” par “Do you like it?” puis de remplacer l’espace vide par le fameux smiley (au survol on consulte les noms des personnes qui ont liké) et le bouton Like/Unlike :



//Change DOM of page to insert Like controls
//Get td with column name : SPBookmark_LikesCount
var headerAnchorName = 'SPBookmark_' + likeFieldName;
var fieldid = '#SPFieldLikes';
	
//get td with column header => change text
$('a[name=' + headerAnchorName + ']').parent('h3').text("If you like it");
	
//get td with field value => add controls to like/unlike etc.
//add like control with smiley, number of likes, etc.
if(likesCount == 0 || userAlreadyLike == false) {

   htmlresult += 'Like';

}
else if (userAlreadyLike == true) {
   
   htmlresult += 'Unlike';

}

   //clear field content then insert buttons, icons etc.
   $(fieldid).empty();
   $(fieldid).append(htmlresult);
}

//Function called if refresh data on like/unlike controls fails
function onLoadItemDataFailed(sender, args) {
   alert('ERROR !');
   console.log('Error when loading item data.');
}

4.3 Gérer les likes/unlikes

Enfin, il faut développer les fonctions qui gèreront les clics utilisateur sur le bouton Like/Unlike. Pour cela, il faut s’assurer que “reputation.js” soit bien chargé puis appeler la fonction “Microsoft.Office.Server.ReputationModel.Reputation.setLike()” sans oublier executeQueryAsync() pour exécuter la requête :


//set like or unlike on selected item when current user clicks on like / unlike button
function setLikeOnNews(listId, itemId, like, itemtitle) { 

   var clientContext = new SP.ClientContext();
   //register native JS for social capabilities	
   //set like. If like == true => Like item ; if like == false => Unlike item	
   EnsureScriptFunc('reputation.js', 'Microsoft.Office.Server.ReputationModel.Reputation',
      function () {                     
         Microsoft.Office.Server.ReputationModel.Reputation.setLike(clientContext,listId,itemId, like);
  
         clientContext.executeQueryAsync(
               Function.createDelegate(this, function(){onQuerySucceeded(listId, itemId, like, itemtitle);}),
	       Function.createDelegate(this, onQueryFailed));
       }
   );
}

4.4 Afficher une notification

Petit bonus, j’ai choisi d’afficher une popup non-persistante afin d’avoir un retour utilisateur et confirmer que le like/unlike a bien été pris en compte. Pour cela :


//If like function is ok (without error)
function onQuerySucceeded(listId, itemId, like, itemtitle) {
   //Display a notification and change text on like/unlike link
   var message = "";
   if(like == "true") {
      var message ="You like the item";
   }
   else if(like == "false") {
      var message ="You unlike the item ";
   }
   else {
      var message ="An error occurred. Please try again";
   }
	
   //Display a popup on top right corner to confirm like / unlike
   var extraData = new SPStatusNotificationData(
   STSHtmlEncode(''),
   STSHtmlEncode(decodeURIComponent(itemtitle)),
   _spPageContextInfo.webLogoUrl
   );
 
   var myNotification = new SP.UI.Notify.Notification(
   SPNotifications.ContainerID.Status,
   STSHtmlEncode(message),
   false,
   '',
   function () { },
    extraData
   );
 
   myNotification.Show();
	
   //refresh data on tooltip (likers, number of likes)
   refreshLikeData(listId, itemId, like, itemtitle);	
}

//If like function throws an error
function onQueryFailed(sender, args) {
   //display an error
   var message = "An error occurred when you try yo like the item. : " + args.get_message();
   var notifyId = SP.UI.Notify.addNotification(message, false);
}

4.5 Mettre à jour les contrôles après un like/unlike

Bien sûr, après que l’utilisateur ait liké/déliké (anglicisme… quand tu nous tiens), il convient de rafraichir les contrôles affichés afin d’incrémenter/décrémenter le nombre de likes, la liste des personnes ayant liké et également modifier le bouton pour pouvoir déliké si on a liké et inversement.

Pour cela, il faut recharger l’item courant en utilisant la même technique que pour le premier chargement :


//Refresh data when user is liking / unliking an item
function refreshLikeData(listId, itemId, like, itemtitle) {
   //get data from list item
   var clientContext = SP.ClientContext.get_current();
   var list = clientContext.get_web().get_lists().getById(listId);
   clientContext.load(list, 'Title', 'Id');
   var item = list.getItemById(itemId);
   clientContext.load(item, "LikedBy", "ID", "LikesCount", "Title");
   clientContext.executeQueryAsync(
         Function.createDelegate(this, function(){onRefreshLoadDataSucceeded(itemId, like, item, list);}),
         Function.createDelegate(this, onRefreshLoadDataFailed)
   );
}

Et enfin on injecte les mises à jour toujours via du JQuery (que j’aurai pu factoriser…) :



//when refresh data succeeds, change html controls like/unlike and tooltip, number of likes
function onRefreshLoadDataSucceeded(itemId, like, item, list) {
	
   //set number of likes
   $('.ms-comm-likesCount.ms-comm-reputationNumbers').text(item.get_item('LikesCount'));
	
   //change like button to unlike or unlike to like (or error) + command onclick
   if(like == "true") {
      $('a#likesElement-' + itemId).text('Unlike');
      $('a#likesElement-' + itemId).attr("onclick" , 'setLikeOnNews("' + list.get_id() + '","' + item.get_item('ID') + '","false","' + encodeURIComponent(item.get_item('Title')) + '");return false;');
   }
   else if(like == "false") {
      $('a#likesElement-' + itemId).text('Like');
      $('a#likesElement-' + itemId).attr("onclick" , 'setLikeOnNews("' + list.get_id() + '","' + item.get_item('ID') + '","true","' + encodeURIComponent(item.get_item('Title')) + '");return false;');
   }
   else {
      $('a#likesElement-' + itemId).text('ERROR');
      $('a#likesElement-' + itemId).attr("onclick" , '');
   }
	
   //change tooltip on like/unlike button
   var likers = [];
   var likerslist = '';
   var likerslimit = 5;
   var likerslimitOverpass = false;
   var currentUserId = _spPageContextInfo.userId;
   //Set likers on span
   if(item.get_item('LikesCount') != 0) {
      var likedBy = item.get_item('LikedBy');
		
      if (!SP.ScriptHelpers.isNullOrUndefined(likedBy)) {
         for (var i = 0; i < likedBy.length; i++) {
			
            likers[likers.length] = {
		id: String(likedBy[i].get_lookupId())
		, title: likedBy[i].get_lookupValue()
	    };
				
	    if (likers[i].id == currentUserId) {
               userAlreadyLike = true;
               likerslist = 'You \r' + likerslist;
            }
            else if(i < likerslimit) {
               likerslist += likers[i].title + '\r';					
            }
            else
               likerslimitOverpass = true;
            }
            if(likerslimitOverpass == true) {
               likerslist += '...\r';
            }	
         }
	else {
           likesCount = 0;
         }
      }
      else {
         likesCount = 0;
      }   	
	
   $('.ms-comm-likesMetadata.ms-metadata').attr('title',likerslist.replace(/\r$/, ""));
}

//Function called if refresh data on like/unlike controls fails
function onRefreshLoadDataFailed(sender, args) {
   //set number of likes
   $('.ms-comm-likesCount.ms-comm-reputationNumbers').text(item.get_item('ERROR'));
   $('a#likesElement-' + itemId).text('ERROR');
   $('a#likesElement-' + itemId).attr("onclick" , '');
}

Et tout devrait fonctionner ! La preuve en images… et en français :
15

16

Voici donc un exemple “assez simple” d’une personnalisation, sans code serveur, sans solution à déployer… et qui ouvre la porte à de nouvelles personnalisations.
Et je sais que certains vont me poser la question : “Mais ça y sera dans SP2016 ?” ===> La réponse est OUI 🙂

A bientôt !

[SharePoint] – Script PowerShell pour afficher les tailles des bases de données

Posted on Updated on

Bonjour à tous,

Aujourd’hui un petit script bien utile qui vous permettra d’afficher la taille des bases de données d’une ferme SharePoint OnPremise.

Cela permettra à l’administrateur de ferme principalement de suivre l’évolution du stockage dans la ferme SharePoint, afin d’affiner ses quotas, optimiser son serveur / cluster SQL Server.

Le but est donc de créer un petit script qui parcourra les Web Applications, puis les bases de données qui leur sont associées (on ne sélectionne donc pas les bases de données des Applications de Service) et d’afficher le tout dans une GridView par exemple.

Dans cette démo, j’utiliserai l’environnement PowerShell ISE (Integrated Scripting Environment), avec Windows Server 2012 et une plateforme SharePoint Server 2013 Enterprise (Pré-SP1).

Première étape, lancer PowerShell ISE avec le compte Administrateur de la ferme SharePoint :

02

Et entrer le script tout fait 🙂

Ok, je vais détailler un peu son contenu :

Première étape, afin que l’on puisse lancer le script avec PowerShell, sans utiliser le SharePoint Management Shell, on ajoute l’import des Cmdlets SharePoint :

If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null ) 
{ Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell }

$host.Runspace.ThreadOptions = "ReuseThread"

Puis on démarre un scope pour les objets utilisés dans le script afin qu’ils soient automatiquement “Disposés” à la fin de l’exécution. Pour cela, nous allons utiliser les commandes (au début et à la fin du script) :

Start-SPAssignment –Global
Stop-SPAssignment –Global

Plus de détails ici : http://technet.microsoft.com/fr-fr/library/ff607664(v=office.15).aspx

On commence ensuite la construction dun tableau (Hashtable plus particulièrement) en parcourant les WebApplications, les bases de contenu et en calculant leur taille en GB :

$webApps = Get-SPWebApplication -IncludeCentralAdministration
foreach($WebApp in $spWebApps)
{
    $ContentDBs = $webApp.ContentDatabases
    foreach($ContentDB in $ContentDBs)
    {    
        $size = [Math]::Round(($ContentDB.disksizerequired/1GB),2)

        $DBdetails = New-Object PSObject
        $DBdetails | Add-Member -Name "Web Application Name" -MemberType NoteProperty -Value $WebApp.DisplayName
        $DBdetails | Add-Member -Name "Database Name" -MemberType NoteProperty -Value $ContentDB.Name
        $DBdetails | Add-Member -Name "Database Size (in Gb)" -MemberType NoteProperty -Value $size         $data += $DBdetails
    }
}

Puis pour terminer, on affiche le tout dans une GridView :

$DB = $data | Out-GridView -Title "SharePoint Databases Size" –PassThru

Il nous faut ajouter un try/catch pour gérer les exceptions… ce qui donne au final :

03

Puis on lance l’exécution du script (sauvegardé dans un fichier PS1) ou avec le bouton “Play” de PowerShell ISE :

05

Et voilà !

[SP2013] – Déployer le Machine Translation Service de SharePoint Server 2013

Posted on Updated on

Bonjour à tous.

Dans cet article je vais tenter de vous expliquer ce qu’est le Machine Translation Service de SharePoint Server 2013 mais également comment le déployer sur votre ferme SharePoint.

J’ai choisi de déployer et configurer un maximum de choses avec PowerShell dans le but d’automatiser le déploiement.

1/ Machine Translation Service : qu’est-ce que c’est ?

Le Machine Translation Service est une nouvelle application de service, apparue avec SharePoint 2013 et disponible dans les versions Standard et Enterprise.

Il permet de traduire automatiquement non seulement les sites (colonnes, listes, pages) mais également le contenu des documents qui seront stockés dans ce site, et ce à la demande des utilisateurs. D’ailleurs ce contenu peut être pré-traduit (via une planification et un TimerJob) ou bien à la volée sur la demande d’un utilisateur.

On comprendra rapidement l’intérêt de ce service lors du déploiement de portails de publication SharePoint utilisant les Variantes.

Plutôt intéressant sur le principe !

Vous trouverez également sur Technet quelques exemple d’appels à API du Machine Translation Service via du code client ou serveur : http://msdn.microsoft.com/fr-fr/library/office/jj163145(v=office.15).aspx.

De plus, ce service limite la taille des fichiers qui pourront être convertis :

Type de fichier / extensions Limite de taille (en Ko)
Texte (txt) 15 360
HTML (html, xhtml, xhtm, htm, aspx) 15 360
Word (doc, docx, docm, dot, dotx, dotm, rtf) 524 288
XLIFF (xlf) 15 360

2/ Prérequis avant le déploiement

Le déploiement de ce service impose quelques prérequis qu’il vous faudra valider ou mettre en œuvre au préalable.

A. Application de service : Gestion des applications

Effectivement, cette application de service Gestion des applications ‘'(App Management Service Application) doit être déployée et configurée sur votre ferme. Pour cela, je vous invite à suivre le guide de déploiement sur Technet : http://technet.microsoft.com/fr-fr/library/fp161236(v=office.15).aspx

B. Application de service : SharePoint Token Service

Le service d’authentification serveur à serveur (STS) doit être déployé et configuré dans le cas où vous travaillez sur une architecture Multi-Tenant. Pour cela, je vous invite à suite le guide de déploiement sur Technet : http://technet.microsoft.com/fr-fr/library/jj655400(v=office.15).aspx

C. Application de service : User Profile

Peut-être un peu plus étonnant, votre ferme doit avoir le Proxy de l’application de service User Profile déployé sur votre ferme SharePoint, et l’application de service correspondante doit être déployée, configurée et démarrée. Pour cela, je vous invite à suivre le guide de déploiement sur Technet : http://technet.microsoft.com/fr-fr/library/ee721052(v=office.15).aspx

D. Accès à internet

Evidemment, ce n’est pas SharePoint qui va effectuer les traductions demandées par les utilisateurs mais bien envoyées et traduites par Microsoft Translation Service. Et donc pour cela, une connexion Internet sur les serveurs SharePoint est requise (ceux où le service de traduction est démarré).

E. Compte de déploiement du service

Evidemment, pour pouvoir déployer et configurer le service, il faut avoir suffisamment de droits. Dans mon cas j’utilise le compte système (compte d’installation de la ferme SharePoint).

De manière générale, ce compte doit avoir les droits :

  • securityadmin sur l’instance SQL Server de votre ferme SharePoint
  • db_owner sur l’instance SQL Server de votre ferme SharePoint
  • Dans le groupe Administrateurs local de vos serveurs SharePoint où on lancera le déploiement

F. Compte du pool d’application

Dans l’exemple que je vais développer ci-après, j’utilise un nouveau pool d’application pour ce service. Il est nécessaire que le compte utilisé par ce pool ait accès au service User Profile avec le contrôle total. Pour cela, il faut se rendre dans la page de gestion du service de profil utilisateur dans la central admin et ajouter le compte avec contrôle total :

12

3/ Déploiement du service avec PowerShell

Ma ferme SharePoint est simple, elle est composée :

  • D’un serveur Controleur de Domaine (AD, windows server 2008R2 + DNS)
  • D’un serveur SharePoint Server 2013 Enterprise EN (+ language pack FR) sans SP1 (Windows Server 2012)

Voici les applications de service déployées sur ma ferme :

02

Une fois les prérequis vérifiés, nous pouvons lancer le SharePoint Management Shell en s’étant au préalable loggé sur le serveur avec le compte qui a les bons droits :

01

Nous allons commencer par créer un nouvel application pool (possible d’utiliser un existant)  et positionner les variables utiles :

#Variables
$servicename = "Machine Translation Service"
$serviceproxyname = $servicename + " Proxy"
$databasename = "SharePoint_MTS"
$databaseserver = "SP2013\SQL2012"
$apppoolname = "SharePoint_MTS_AppPool"
$apppoolaccount = "demo\spappservice"

$apppool = New-SPServiceApplicationPool -Name $apppoolname -Account $apppoolaccount

03

NB : (source Technet) Le compte utilisé par le pool d’applications doit également disposer d’autorisations de contrôle total sur l’application de service de profil utilisateur. Si vous créez un pool d’applications et un compte, veillez à ajouter le compte à la liste des comptes qui peuvent utiliser l’application de service de profil utilisateur, puis accordez les autorisations de contrôle total à ce compte. Pour plus d’informations, voir Limiter ou activer l’accès à une application de service (SharePoint 2013).

Puis l’on va créer l’application de service avec la commande :

New-SPTranslationServiceApplication -Name $servicename -DatabaseName $databasename -DatabaseServer $databaseserver -ApplicationPool $apppoolname –Default

04

05

L’application de service est maintenant créée, il faut démarrer le service sur le serveur :

Get-SPServiceInstance | where-object {$_.TypeName -eq "Machine Translation Service"} | Start-SPServiceInstance

06

07

4/ Configuration du service avec PowerShell

L’application de service étant créée, nous pouvons maintenant la configurer avec PowerShell.

Pour cela, toujours dans le SharePoint Management Shell, nous allons fixer :

  • La fréquence d’exécution du TimerJob de traduction : 15min
  • Le nombre maximal d’essais pour la traduction : 5
  • Le nombre de jours de conservation des travaux de traduction terminés (historique) : 30
  • Le nombre maximal de demandes de traductions synchrones : 100
  • Le nombre maximal de documents à convertir avant le redémarrage de la conversion : 300

Pour cela, nous allons utiliser la commande suivante :

Set-SPTranslationServiceApplication -Identity $servicename -EnableAllFileExtensions -UseDefaultlnternetSettings -TimerJobFrequency 15 -MaximumTranslationAttempts 5 -JobExpirationDays 30 -MaximumSyncTranslationRequests 100 -RecycleProcessThreshold 300 -DisableBinaryFileScan 1

08

Notez bien qu’il faut redémarrer le service juste après, comme précisé dans le Management Shell. Et donc :

Get-SPServiceInstance | where-object {$_.TypeName -eq "Machine Translation Service"} | Stop-SPServiceInstance

Get-SPServiceInstance | where-object {$_.TypeName -eq "Machine Translation Service"} | Start-SPServiceInstance

09

Les paramètres sont bien appliqués dans les paramètres de l’application de service :

10

11

Voilà, c’est bon pour la configuration !

5/ Vérification de la traduction

Pour vérifier le bon fonctionnement de tout cela, j’ai créé une nouvelle collection de sites de type Publishing portal, en Anglais :

13

Sur la page d’accueil du site, on propose directement un lien “Make your site multilingual”. Nous allons pouvoir créer les variantes et leurs étiquettes directement depuis cette page (ou depuis les paramètres du site). Je définis donc une variante par défaut en anglais et une en français :

14

Lors de la création du label français, on propose d’utiliser les service du Machine Translation Service : 15

16

17

Lorsque les étiquettes de variations sont créées, il faut patienter quelques minutes afin que le TimerJob qui créée les hiérarchies soit exécuté. Pour forcer la chose, il vous suffira de lancer ce job manuellement depuis la console d’administration centrale de SharePoint, dans la section “Monitoring” > “Review job definitions” et de trouver le job appelé “Variations Create Hierarchies Job Definition” associé à la WebApplication sur laquelle le portail de publication est créé. Puis de cliquer sur le bouton “Run Now”.

Les variations sont maintenant créées :

18

Et nous pouvons maintenant aller sur les deux variations EN / FR :

19

20

Dans le ruban, dans l’onglet VARIANTES, on a maintenant le bouton “Traduire automatiquement” :

21

 

Un message apparait nous informant que quelques configurations sont encore nécessaires et nous seront notifiés par e-mail :22

A noter au passage que la traduction n’est pas possible depuis le site anglais, puisque c’est la variation “maitre” (pas d’onglet VARIANTES) :

23

Vous pouvez également suivre l’avancement de la traduction via le bouton “Etat de la traduction” dans l’onglet VARIANTES

24

 

Et avec des documents ?  Je me rends donc sur le site Français et j’upload dans la bibliothèque de documents Documents un fichier Word (docx) contenant la recette du cheesecake en anglais. Ce fichier s’appelle cheesecake.docx, et volontairement j’utilise un compte collaborateur sur ma collection de sites appelé “Lenny” :

29

25

A noter la présence du champ “Etat de la traduction” qui est par défaut à la valeur “Traduction effectuée”. J’ai modifié la valeur pour mettre “Traduction demandée”. Pour autant la traduction ne sera pas lancée automatiquement.

Je sélectionne alors l’élément et je clique sur VARIANTES dans le ruban, et je clique sur Traduire automatiquement > Elements sélectionnés uniquement :

26

La traduction démarre :

27

La traduction est terminée, le champ Etat de la traduction est maintenant à la valeur “Traduction effectuée” :

28

Ouvrons le fichier pour voir ce qu’il en est ! Le fichier est “bien” traduit. En effet, cela ne vaudra jamais une belle traduction littéraire, mais cela dit ça reste compréhensible :

30

Vous pouvez également suivre l’état d’avancement de la traduction en utilisant le bouton “Etant de la traduction” dans l’onglet VARIANTES :

31

32

 

Voilà, c’est tout pour aujourd’hui !

[SP2010 & SP2013] – Envoyer les résultats de l’analyseur de santé et d’intégrité par e-mail

Posted on Updated on

 

Bonjour à tous.

Cela fait quelques temps que je n’avais rien publié, je reviens avec un script bien pratique permettant d’envoyer les résultats produits par l’analyseur de santé et d’intégrité de SharePoint (SharePoint Health Analyzer) par e-mail, à l’administrateur par exemple.

Le but étant de ne plus avoir à se connecter à l’administration centrale de SharePoint pour consulter et monitorer l’état de la plateforme, mais d’automatiser cela par un envoi de courrier électronique.

Pour cela, nous allons écrire un script permettant de récupérer le contenu des résultats, récupérer les paramètres d’envoi de courrier électronique et enfin automatiser le tout via une tâche planifiée. Et bien sûr compatible avec SharePoint 2010 et SharePoint 2013 !

1/ Récupérer les paramètres d’envoi d’e-mail

NB : le script doit être exécuté avec un compte possédant les droits nécessaires pour effectuer les opérations. Dans mon cas c’est l’administrateur de ferme SharePoint.

Pour cela, c’est très simple. Nous allons écrire un script PowerShell permettant de récupérer l’instance du site d’administration centrale de SharePoint puis récupérer les paramètres de courrier sortant (Outgoing e-mail parameters).

Pour récupérer la Web Application de l’administration centrale, soit on connait l’URL soit on ne la connait pas.

Dans le cas où on la connait (il faudra la modifier lorsque l’on changera de ferme… et si elle change d’url / serveur) :

$w = Get-SPWebApplication http://sitename

Si on ne la connait pas, et si on veut faire un script portable (mon cas) :

$CAWebApp = (Get-SPWebApplication -IncludeCentralAdministration) | ? { $_.IsAdministrationWebApplication -eq $true }

$CARootWeb = Get-SPWeb -Identity $CAWebApp.Url

Ce qui donne :

01

On récupère bien l’adresse du site Web (racine) de la Web Application contenant la centrale d’administration de notre ferme SharePoint.

Ensuite, nous allons récupérer les paramètres :

  • L’adresse de provenance (From)
  • L’adresse (le nom) du serveur d’envoi d’e-mails (renseigné dans la console d’administration centrale de SharePoint).
$from = $CAWebApp.OutboundMailReplyToAddress

$mailserver = $CAWebApp.OutboundMailServiceInstance.Server.Address

Et également fournir l’adresse où l’on souhaite envoyer le courrier électronique :

$to = "admin.sharepoint@demo.local"

02

2/ Récupérer le contenu du SharePoint Health Analyzer

Le SharePoint Health Analyzer enregistre ses résultats dans une liste SharePoint dont l’adresse est statique (toujours la même), dans le site racine de l’administration centrale SharePoint.

Il suffit donc de se connecter à cette liste, d’en récupérer le contenu pour le formater dans le corps du courrier électronique.

Récupérons l’instance de la liste de résultats :

$list = $CARootWeb.GetList("\Lists\HealthReports")

03

Il nous reste ensuite à récupérer le contenu de cette liste et le formater dans un contenu HTML qui deviendra le corps de l’e-mail. Pour récupérer le contenu, rien ne vaut une petite requête CAML !

Ici nous voulons récupérer seulement les cas qui ne sont pas en réussite (succès), c’est-à-dire les problèmes. Il faut donc filtrer sur un champ qui s’appelle “HealthReportSeverity” (internalName, en anglais dans mon ca), en ne récupérant que les items où la valeur est différente de “4 – Success” :

$where = "<Where><Neq><FieldRef Name='HealthReportSeverity' /><Value Type='Text'>4 - Success</Value></Neq></Where>"
$query = New-Object Microsoft.SharePoint.SPQuery
$query.Query = $where
$items = $list.GetItems($query)

Dans mon cas, je récupère 3 items ($items.Count) :

04

3/ Construire le contenu du courrier électronique

Le contenu étant récupéré, il nous faut construire le corps du message en HTML (très basique !). Pour ma part, je suis parti sur quelque chose de simple: un tableau.

Ce tableau contiendra :

  • Le nom de l’erreur avec un lien pointant vers le détail (vers la page DispForm.aspx de SharePoint)
  • Le Type (catégorie) d’erreur
  • Le contenu du message
  • Le type d’erreur : avertissement, erreur, etc.
  • La date d’exécution (de la tâche planifiée SharePoint)

Nous allons également ajouter un peu de texte avant et après le tableau pour préciser :

  • La date et l’heure courante
  • Le nom du rapport
  • Une signature

On construit l’entête et la signature :

NB : Attention à l’encodage des simples et double quotes !!! => Passer par NotePad / Notepad++, ça vous aidera 🙂

$entete = "Bonjour, voici le rapport d’exécution de l’analyseur de santé et d’intégrité de la ferme SharePoint : " + $CAWebApp.Farm.Name

$titre = "<Title>" + $entete + "</Title>"

$signature = "Bonne journée, <br/><br/>L’équipe SharePoint."

05

Puis nous allons construire le tableau en itérant sur la collection d’Items chargée via la requête CAML :

$corps = "<h2>" + $entete + "</h2><br />"

$corps = $corps + "<table cellspacing='5' cellpadding='5' style='width: 100%;border:1px solid #bbbbbb'>" 
foreach ($item in $items)
{
$itemTitle = $item.Title
$itemUrl = $CARootWeb.Url + ($list.Forms | where { $_.Type -eq "PAGE_DISPLAYFORM" }).ServerRelativeUrl + "?ID=" + $item.ID

$itemSeverity = $item["Severity"]
$itemCategory = $item["Category"]
$itemExplanation = $item["Explanation"]
$itemModified = $item["Modified"]

$corps = $corps + "<tr>"
$corps = $corps + "<td><a href=`"" + $itemUrl + "`">" + $item.Title + "</a></td>"
$corps = $corps + "<td>" + $itemCategory + "</td>"
$corps = $corps + "<td>" + $itemExplanation + "</td>"
$corps = $corps + "<td>" + $itemSeverity + "</td>"
$corps = $corps + "<td>" + $itemModified + "</td>"
$corps = $corps + "</tr>"
}

$corps = $corps + "</table><br /><br />" + $signature

$corpshtml = ConvertTo-Html –Head $titre –Body $corps

06

07

4/ Envoyer un e-mail en PowerShell

Ensuite il nous faut envoyer cet e-mail via des cmdlets PowerShell. Pour cela, nous allons recourir à l’API System.Net.Mail bien connue dans le monde Microsoft :

$CARootWeb.Dispose()
Send-MailMessage –From $from –To $to –Subject $titre –BodyAsHtml $corps –SmtpServer $mailserver

Puis fermer la connexion sur la Web Application :

$CARootWeb.Dispose()

Attention, dans cet exemple j’ai configuré le service SMTP sur mon serveur SharePoint, et en renseignant correctement les paramètres d’e-mails sortants dans la console d’administration centrale de SharePoint.

5/ Automatiser l’envoi par une tâche planifiée Windows

Dernière étape, l’automatisation. Pour cela nous allons créer une tâche planifiée Windows, exécutée sur l’un des serveurs SharePoint de la ferme. Dans mon cas ce sera sur le serveur hébergeant l’Administration Centrale de SharePoint.

Cette tâche planifiée devra lancer PowerShell, puis appeler le script. Il nous faut donc modifier à nouveau ce script pour intégrer l’appel du Snap-In permettant de charger le contexte SharePoint dans PowerShell (ce que fait le Management Shell de SharePoint, automatiquement).

Je vous invite à vous reporter à http://technet.microsoft.com/fr-fr/library/ee806878(v=office.15).aspx.

Nous allons alors ajouter en haut du fichier du script PowerShell :

if ((Get-PSSnapin "Microsoft.SharePoint.PowerShell" –ErrorAction SilentlyContinue) -eq $null)
{
Add-PSSnapin "Microsoft.SharePoint.PowerShell"
}

Et enregistrer le tout dans un fichier avec l’extension ps1. Pour moi SPHealthAnalyzerSendMail.ps1, que je tente d’exécuter avec PowerShell (et non pas le Management Shell de SharePoint :

14

 

Voici le fichier obtenu, vous pouvez le télécharger ici : http://1drv.ms/1ot9VJI

Créons donc cette tâche planifiée ! Pour cela, il faut ouvrir l’assistant de création des tâches panifiées de Windows Server :

Dans Démarrer > Outil d’administration > Tâches planifiées :

image

image

 

Cliquer sur “créer une tâche” dans le panneau Actions à droite et donnez-lui un nom, description, et surtout le compte exécutant la tâche (l’administrateur de la ferme dans mon cas) :

image

 

Aller dans l’onglet Triggers (déclencheur) et fournir une planification (schedule), dans mon cas chaque jour à 2h00 du matin :

image

 

Puis aller dans l’onglet Actions et entrer les paramètres :

  • Commande : C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
  • Arguments : –command “.\\SPHealthAnalyzerSendMail.ps1”
  • Répertoire de démarrage : Répertoire où est enregistré votre fichier sur le serveur, dans mon cas dans le répertoire 14 == C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14

image

 

Enregistrer le tout, l’assistant vous demande le mot de passe du compte utilisé pour lancer la tâche :

image

 

La tâche est créée :

image

 

Faites un clic droit, Démarrer pour tester :

image

 

Les résultats de l’exécution sont présentés dans la fenêtre en bas :

image

 

Voici l’e-mail reçu… C’est simple et épuré dira-t’on. Si vous rencontrez des problèmes d’encodage pour les caractères accentués par exemple, n’hésitez pas à jouer avec la fonction :

[System.Web.HttpUtility]::HtmlEncode(“MON TEXTE A ENCODER”)

15

 

Il n’y a plus qu’à revoir un peu le Html envoyé dans l’e-mail pour peaufiner, et c’est tout bon !

[SharePoint 2010 – 2013] – Créer une Target Application sans le Secure Store Service en PowerShell

Posted on Updated on

 

Bonjour à tous,

Cela faisait un petit moment que je n’avais pas publié. Un petit post aujourd’hui pour vous montrer comment ajouter une TargetApplication dans le Secure Store Service de SharePoint. Allons-y !

 

1/ Secure… quoi ?

Le Secure Store Service, appelé Banque d’Informations Sécurisées en français), est une application de service de SharePoint 2010 et 2013 qui vous permet de stocker des couples d’identifiants login/password dans une base encryptée. Ces couples d’identifiants sont destinés à l’usage d’autres applications de services : Business Connectivity Service, PowerPivot, Excel Services, etc. afin qu’ils soient en capacité à se connecter à des sources de données par exemple, avec des identifiants différents de ceux de l’utilisateur connecté, du pool d’application, du compte administrateur.

Dans mon cas, il s’agit de stocker des identifiants afin qu’une application personnalisée puisse se connecter à un serveur Exchange 2010 via ses WebServices. Je ne voulais pas stocker ces informations dans SharePoint ou dans un fichier de configuration par exemple. L’avantage étant que ces paramètres sont cryptés et modifiables par l’administrateur de la ferme.

 

2/ Prérequis

En prérequis, il faut bien sûr déployer cette application de service qui sera disponible pour :

  • · SharePoint Server 2010 Standard
  • · SharePoint Server 2010 Enterprise
  • · SharePoint Server 2013 Standard
  • · SharePoint Server 2013 Enterprise

Point sur n’importe laquelle des versions Foundation ni SharePoint 2007 donc.

Pour déployer et configurer cette application de service, je vous invite à lire : http://technet.microsoft.com/fr-fr/library/ee806866(v=office.15).aspx

 

3/ Un peu de PowerShell

Cette démo sera réalisée avec SharePoint Server 2010 Enterprise.

Pour commencer, nous allons lancer le Management Shell de SharePoint (PowerShell avec les assemblies/cmdlets nécessaires à l’utilisation avec SharePoint). Pour cela, vous trouverez le raccourci dans Démarrer > Tous les Programmes > Microsoft SharePoint 2010 Products > SharePoint 2010 Management Shell

image

 

Nous allons commencer par renseigner quelques variables nécessaires :

  • $siteurl = ” http://sp2010-dev:82/sites/florent&#8221; ==> Url d’un site pour récupérer le ServiceContext (L’application de service Secure Store Service doit être associée à cette WebApplication !)
  • $ta_name = “ExchangeWS” ==> Nom de ma Target Application
  • $ta_friendlyName = “ExchangeWS for DEMO” ==> Nom “Friendly” de ma Target Application
  • $ta_contactEmail = “admin@sp2010.local” ==> Adresse e-mail de contact
  • $ta_owner = “DEMO\spadmin” ==> Propriétaire de la Target Application
  • $ta_userName = “DEMO\exchangeuser” ==> Login à stocker
  • $ta_password = “P@ssw0rd” ==> Password à stocker

image

Puis on créé la Target Application :

$target = New-SPSecureStoreTargetApplication -Name $ta_name -FriendlyName $ta_friendlyName -ContactEmail $ta_contactEmail -ApplicationType Group

clip_image002

Puis on créé les champs Login et password à stocker :

$usernameField = New-SPSecureStoreApplicationField -name “Exchange Username” -Type WindowsUserName -Masked:$false

$passwordField = New-SPSecureStoreApplicationField -name “Exchange Password” -Type WindowsPassword -Masked:$true

$fields = $usernameField,$passwordField

clip_image004

Puis nous allons créer 2 claims pour l’administrateur et pour le propriétaire :

$adminClaims = New-SPClaimsPrincipal -Identity $a_owner -IdentityType 1

$ownerClaims = New-SPClaimsPrincipal -Identity $a_owner -IdentityType 1

clip_image006

Puis créer la nouvelle Target Application :

New-SPSecureStoreApplication -ServiceContext $contextUrl -TargetApplication $ta -Fields $fields -Administrator $adminClaims -CredentialsOwnerGroup $ownerClaims

$ssa = Get-SPSecureStoreApplication -ServiceContext $contextUrl -Name $ta.Name

clip_image008

Puis on charge les identifiants :

$user = ConvertTo-SecureString $ta_userName -AsPlainText -Force

$password = ConvertTo-SecureString $ta_password -AsPlainText -Force

$credentials = $user,$password

Update-SPSecureStoreGroupCredentialMapping -Identity $ssa -Values $credentials

clip_image010

On peut verifier dans l’administration centrale, la Target Application est bien créée :

clip_image012

clip_image014

clip_image016

On voit ici que les Members (utilisateurs ayant accès à la Target Application) contiennent seulement SPADMIN. Pour ajouter des utilisateurs, on peut modifier les Owner Claims…

clip_image018

Par contre, impossible de valider graphiquement si le login/password est bien ajouté, la fenêtre ne charge pas les valeurs chargées (formulaire vide par défaut). Il faut donc tester… et chez moi ça marche 😉

A bientôt !

Florent.

[SharePoint 2013] – Indexation anormalement longue

Posted on Updated on

 

Bonjour à tous.

Aujourd’hui un article / KB concernant le moteur de recherche de SharePoint Server 2013.

Suite à la mise en place de ce moteur de recherche, j’ai pu constater un problème… que je n’avais jamais eu jusque ici !

Concernant le contexte, il s’agit de l’installation de SharePoint Server 2013 Standard en Français, sur Windows Server 2008R2 en Français également et couplé au moteur SQL Server 2008R2 SP1 en Français, installé sur un second seveur.

 

1/ Le problème

 

Lors du déploiement de l’application de service de recherche, j’ai utilisé l’assistant depuis la page de gestion des applications de service dans l’administration centrale de SharePoint.

J’ai nommé mon service “Application de recherche”, utilisé un pool dédié aux applications de service. Lors de la création, aucun problème constaté, le service est bien créé/configuré, les bases de données sont également ok.

Le problème est survenu lors de l’indexation d’une source de données SharePoint (Site SharePoint locaux par défaut) sur un site vide… La première indexation a duré plus de 25 heures !!!!

Evidemment ce n’est pas normal ! Après investigations, sur l’observateur d’évènements, les logs, etc. et activation du mode ‘Verbose” des logs, il s’est avéré que cette erreur se reproduisait constamment lors de l’indexation des données :

 

System.ArgumentException: La longueur de la valeur de la clé ‘application name’ dépasse sa limite fixée à ‘128’.

à System.Data.SqlClient.SqlConnectionString..ctor(String connectionString)     à System.Data.SqlClient.SqlConnectionFactory.CreateConnectionOptions(String connectionString, DbConnectionOptions previous)     à System.Data.ProviderBase.DbConnectionFactory.GetConnectionPoolGroup(DbConnectionPoolKey key, DbConnectionPoolGroupOptions poolOptions, DbConnectionOptions& userConnectionOptions)     à System.Data.SqlClient.SqlConnection.ConnectionString_Set(DbConnectionPoolKey key)     à System.Data.SqlClient.SqlConnection.set_ConnectionString(String value)     à System.Data.SqlClient.SqlConnection..ctor(String connectionString, SqlCredential credential)     à Microsoft.Office.Server.Data.SqlSession.OpenConnection()     à Microsoft.Office.Server.Data.TransactionalSqlSession.RetrySqlConnectionInitialization(Action`1 initializer)     à Microsoft.Office.Server.Data.TransactionalSqlSession.OpenConnection()     à Microsoft.Office.Server.Data.SqlSession.ExecuteNonQuery(SqlCommand command) à Microsoft.Office.Server.Search.ManagedSqlSession.ExecuteNonQuery()

SqlCommand: ‘SET XACT_ABORT ON’     CommandType: Text CommandTimeout: 0

 

 

Bon évidemment premier réflexe… un coup de moteur de recherche… pas vraiment concluant. J’ai donc supprimé l’application de service, recréé… et même erreur !

 

 

La solution

 

En fait… ce n’est pas si compliqué que ça ! En nommant mon application de service de recherche “Application de recherche”, l’assistant nomme les bases de données :

“Application_de_recherche_[UN MEGA GUID PAS BEAU]”.

Et il semblerait que la connectionstring soit trop longue !!!!!!! (dépasse les fameux 128 caractères stipulés dans le log de l’erreur)

 

La solution peut donc être de deux formes. Soit on recréé une application de service de recherche à l’aide de l’assistant, en choisissant un nom plus court… et en priant pour qu’il soit assez court.

Soit on déploie le service avec notre ami PowerShell / Management Shell pour SharePoint.

Et vous l’aurez compris… je préfère largement la seconde option.

Voici donc le script que j’ai utilisé pour recréer ce service :

 

Création du pool d’application pour notre service :

  • $appPoolName = Nom du pool : SharePointSearchAppPool
  • $appPool = Pool d’application créé
    • Compte : DEMO\spapppool ==> domaine : Demo, compte utilisé : spapppool

 

$appPoolName = “SharePointSearchAppPool”
$appPool = New-SPServiceApplicationPool -Name $appPoolName -Account “DEMO\spapppool”

 

 

Divers paramètres :

  • $searchServerName  = Nom du serveur de recherche
  • $serviceAppName = Nom du service d’application
  • $searchDBName = Nom de la base de données du service

 

$searchServerName = (Get-ChildItem env:computername).value
$serviceAppName = “Application de recherche”
$searchDBName = “SPSearch_DB”

 

 

Démarrage des services sur le serveur :

 

Start-SPEnterpriseSearchServiceInstance $searchServerName
Start-SPEnterpriseSearchQueryAndSiteSettingsServiceInstance $searchServerName

 

 

Création de l’application de service de recherche et récupération de l’instance :

 

$searchServiceApp = New-SPEnterpriseSearchServiceApplication -Name $serviceAppName -ApplicationPool $appPoolName -DatabaseName $searchDBName
$searchProxy = New-SPEnterpriseSearchServiceApplicationProxy -Name “$serviceAppName Proxy” -SearchApplication $searchServiceApp

$searchServiceInstance = Get-SPEnterpriseSearchServiceInstance

 

 

Clonage de la Topologie de recherche par défaut :

 

$clone = $searchServiceApp.ActiveTopology.Clone()

New-SPEnterpriseSearchAdminComponent –SearchTopology $clone -SearchServiceInstance $searchServiceInstance

New-SPEnterpriseSearchContentProcessingComponent –SearchTopology $clone -SearchServiceInstance $searchServiceInstance

New-SPEnterpriseSearchAnalyticsProcessingComponent –SearchTopology $clone -SearchServiceInstance $searchServiceInstance

New-SPEnterpriseSearchCrawlComponent –SearchTopology $clone -SearchServiceInstance $searchServiceInstance

New-SPEnterpriseSearchIndexComponent –SearchTopology $clone -SearchServiceInstance $searchServiceInstance

New-SPEnterpriseSearchQueryProcessingComponent –SearchTopology $clone -SearchServiceInstance $searchServiceInstance

$clone.Activate()

 

 

Et voilà !

[SharePoint 2013] – Configurer SSL pour SharePoint 2013

Posted on Updated on

 

Bonjour à tous.

Aujourd’hui un article pour vous montrer comment configurer SSL pour utiliser SharePoint 2013 avec des url https et sécuriser l’accès à vos contenus.

Je précise que dans mon cas, je vais utiliser un certificat de type “Self Signed” et donc à utiliser exclusivement pour des plateformes de développement. Pour les environnements de production, il faudra utiliser un certificat “commercial” acquis par exemple auprès de Verisign ou un autre organisme.

Dans ma configuration, j’ai un serveur d’annuaire (Windows Server 2008 avec le Rôle Active Directory) et mon serveur SharePoint (Windows Server 2008R2 SP1, SQL Server 2012 et SharePoint Server 2013 Enterprise).

Voici comment faire pour configurer les différents éléments :

 

1/ Créer un certificat Self Signed & l’exporter

 

Pour cela, nous allons utiliser une fonctionnalité de IIS (7 dans mon cas) permettant de générer des certificats auto-signés.

Nous allons commencer par lancer la console d’administration de IIS (sur le serveur SharePoint), soit en explorant le menu démarrer, soit en exécutant la commande “inetmgr”. Pennons le second cas : cliquer sur “Démarrer > Exécuter > inetmgr” :

image

Puis nous allons cliquer sur le nœud dans l’arborescence portant le nom du serveur SharePoint (SP2013-DEV dans mon cas), et enfin double-cliquer sur l’icône “Server Certificates” dans la zone centrale :

image

 

Sur cet écran, nous allons cliquer sur “Create Self-Signed Certificate…” :

image

 

Dans l’écran suivant, nous allons donner un nom à notre certificat, ici “SharePointCertificate” et cliquer sur OK :

image

Le certificat est maintenant créé. Nous allons maintenant l’exporter dans un fichier. Pour cela, on double-clique sur le nouveau certificat dans la zone centrale :

image

 

Nous allons cliquer sur l’onglet “Details” :

image

 

Et cliquer sur le bouton “Copy To File…” en bas :

image

L’écran d’accueil apparait. On clique sur “Next” :

image

 

Dans l’écran suivant, on conserve le paramètre “No, do not export the private key” et on clique sur “Next” :

image

Ici encore on conserve le paramètre par défaut “DER encoded binary X.509 (.CER)” et on clique sur “Next” :

image

Nous allons ensuite indiquer le chemin où sauvegarder le fichier généré. Dans mon cas je le place sur le Bureau, dans un répertoire nommé “SharePoint Certificate” et le fichier sera nommé “SharePointCertificate.cer”. On clique sur “Next” :

image

 

L’assistant nous affiche le récapitulatif. On clique sur “Finish” :

image

 

L’export est terminé :

image

 

2/ Importer le certificat dans le magasin

 

L’étape suivante consiste à importer le certificat tout juste exporté dans le magasin de certificats du serveur SharePoint.

Pour cela, nous allons lancer une nouvelle console pour les Snap-ins de Windows Server 2008R2 : “Démarrer > Exécuter”. Taper “mmc” et cliquer sur “OK” :

image

La console se lance. Dans “File”, sélectionner “Add/Remove Snap-in…” :

image

Dans la fenêtre apparaissant, sélectionner “Certificates”, et cliquer sur “Add >” :

image

Une fenêtre se lance, sélectionnez “Computer Account” et cliquer sur “Next” :

image

 

Dans l’écran suivant, conserver les paramètres et cliquer sur “Finish” :

image

 

Le Snap-in est bien ajouté, on clique sur “OK” :

image

 

On navigue ensuite dans l’arborescence : Certificates > SharePoint > Certificates :

image

On sélectionne le nœud “Certificates”, clic-droit > All Tasks > Import… :

image

L’assistant se lance, on clique sur “Next” :

image

 

On sélectionne le certificat exporté à l’étape précédente et on clique sur “Next” :

image

 

On conserve les paramètres (vérifier que l’on ait bien “SharePoint” dans le champ “Certificate Store”), “Next” :

image

 

On termine l’import “Finish” :

image

image

On peut maintenant fermer cette console.

 

 

3/ Ajouter le certificat dans l’administration centrale de SharePoint

 

NB : Dans le cas d’un serveur unique, cette étape n’est pas requise.

Nous allons maintenant charger le certificat dans la console d’administration centrale de SharePoint. SharePoint va principalement utiliser ce certificat afin de crypter et signer les échanges entre les serveurs de la ferme (sinon vous aurez des erreurs dans les logs SharePoint).

 

On lance donc le site dans le navigateur et on se rend sur la page : “Security > Manage Trust” :

image

 

Dans la page suivante, on retrouve le certificat utilisé nativement par SharePoint, nous allons ajouter notre certificat en cliquant sur “New” dans le ruban :

image

 

Nous allons ici renseigner le nom (dans mon cas j’ai choisi “SharePointCertificate”) et parcourir le disque local pour retrouver le certificat exporté dans la première étape :

image

On valide le formulaire et le certificat est ajouté :

image

Vous pouvez également automatiser cette configuration avec PowerShell (Management Shell pour SharePoint) :

  • $certificate = new-object system.security.cryptography.x509certificates.x509certificate2(“C:\\User\………\SharePointCertificate.cer”)
  • New-SPtrustedrootauthority –name “SharePointCertificate” –certificate $certificate

 

Etape suivante, configurer les bindings dans IIS

 

4/ Configurer les bindings dans IIS 7

 

Nous allons maintenant indiquer à IIS qu’il doit utiliser un binding https sur l’application Web SharePoint. J’ai bien sûr créé au préalable une Application Web sur le port 80 et une collection de sites.

Nous reprenons donc la console d’administration IIS (inetmgr) et on se rend sur l’application Web du port 80, et on clique sur “Bindings” dans la zone de droite :

image

La fenêtre des Bindings apparait, on clique sur “Add…” :

image

 

Nous allons ajouter un binding en https sur le port 443 (par défaut) et utilisant notre certificat. On clique sur “OK” :

image

Le nouveau binding est ajouté :

image

On ferme la fenêtre avec le bouton “Close”.

 

Dernière étape, configurer les Alternate Access Mapping (Mappage d’Accès de Substitution) dans l’administration centrale de SharePoint.

 

 

5/ Configurer les Alternate Access Mappings

 

Pour configurer ces AAM, on se rend dans la console d’administration centrale de SharePoint, sur la page d’accueil sur “Configure Alternate Access Mapping” :

image

La liste des AAM apparait. On utilise le contrôle permettant de sélectionner une Web Application sur la droite et on choisit celle sur le port 80 :

image

image

On clique ensuite sur “Add Internal Urls” et on ajoute notre url en https, sur la zone default (dans mon cas https://sp2013-dev) et on valide :

image

image

NB : Les deux urls : http et https cohabitent sur la même zone, cela nous permettra d’accéder en http au contenu depuis le réseau local (LAN) et en https depuis l’extérieur (WAN) moyennant d’avoir configurer le reverse proxy (ForeFront Threat Management Gateway, ISA, F5, etc.)… mais ça c’est une autre histoire !

Si vous n’avez qu’un mode d’accès souhaité (https pour tout le monde, vous pouvez ajouter l’url en https dans les Public Urls, sur la zone Extranet par exemple.

 

 

6/ Tests !

 

Nous allons maintenant tester notre configuration. Pour cela, j’utilise un navigateur en entrant l’adresse en https de ma collection de site : https://sp2013-dev :

image

Non ce n’est pas une erreur ! En effet, nous utilisons un certificat Self-Signed, et le navigateur ne fait pas l’approbation par défaut. On clique sur “Continue to this website…” dans le centre de la page :

image

Voila ça fonctionne !