Saturday, 9 September 2017

SharePoint 2013 – On Premises - PowerShell script to import termsets on given site from .CSV file in specific folder.

Hi All,

In this article I’ll explain how to import multiple termsets using .CSV file from one specific folder. Means, all .CSV files (one .CSV file for one termset) are in one folder. PowerShell script will read all the .CSV files from given folder one by one and will import to the term store.

We will also check if group is already exists or not, if not then we will create new group.


Since last 12 years I was working on SharePoint but today I realized more practice / knowledge requiredJ.  I was trying one thing which is not possible.

I was trying to import multiple termsets from one import file (.CSV file) and after long time I realized that this is not possible. Through one import file (.CSV file) we can import only one termset. So if I have multiple termsets to import either I need to create multiple .CSV files or change one .CSV file multiple times.


In our project we need to check in the .CSV files for termsets to TFS so we decided to create the multiple .CSV files. And because of this, this article came. 

I am using Visual Studio 2015 and for PowerShell scripts I have installed “PowerShell Tools for Visual Studio 2015”. PowerShell tools allows us PowerShell script editing and debugging in Visual Studio.

Steps:
1.      Check whether SharePoint snap in is loaded or not. If not then loading SharePoint snap in.

if(-not(Get-PSSnapin | Where { $_.Name -eq "Microsoft.SharePoint.PowerShell"}))
{
       Add-PSSnapin Microsoft.SharePoint.PowerShell;
}

2.      Get the site / your site collection where termsets need to be imported

$site = Get-SPSite -Identity <“Your site collection URL”>

3.      Get the taxonomy session and term store
$session = new-object Microsoft.SharePoint.Taxonomy.TaxonomySession($site)

#Here we are assuming "Managed Metadata Service" termstore is available
$termstore = $session.TermStores["Managed Metadata Service"]

4.      Taxonomy group – Checking if group is already exist or not. If not we will create a new group.
# Check for Taxonomy Group

$termGroup = <“Your group name”>
       $group = $termstore.Groups[$termGroup]

       # Check if group exists or not
       if (!$group)
       {
              # creating the group
              $group = $termstore.CreateGroup($termGroup);
              $termstore.CommitAll()
}

5.      Import manager : Get the import manager from Term Store

#getting Import manager for the Term Store
$manager = $termstore.GetImportmanager()

6.      Importing each .CSV file :
#folder path
$termsFolderPath =<Your folder path where all .csv files>”

#read all files
$files = ([System.IO.DirectoryInfo] (Get-Item $termsFolderPath)).GetFiles()
#looping through all files
ForEach($file in $files)
       {
              $reader = new-object System.IO.StreamReader($file.FullName)
      
              #output variables
              $alltermsadded = $false
              $errormessage = ""
       #import the termset file
       $manager.ImportTermSet($group, $reader, [ref] $alltermsadded, [ref] $errormessage)
}

Complete Script:

if(-not(Get-PSSnapin | Where { $_.Name -eq "Microsoft.SharePoint.PowerShell"}))
{
       Add-PSSnapin Microsoft.SharePoint.PowerShell;
}

$site = Get-SPSite -Identity <“Your site collection URL”>

$session = new-object Microsoft.SharePoint.Taxonomy.TaxonomySession($site)

#Here we are assuming "Managed Metadata Service" termstore is available
$termstore = $session.TermStores["Managed Metadata Service"]

# Check for Taxonomy Group
$termGroup = <“Your group name”>
       $group = $termstore.Groups[$termGroup]

       # Check if group exists or not
       if (!$group)
       {
              # creating the group
              $group = $termstore.CreateGroup($termGroup);
              $termstore.CommitAll()
}

#getting Import manager for the Term Store
$manager = $termstore.GetImportmanager()
#folder path
$termsFolderPath =<Your folder path where all .csv files>”

#read all files
$files = ([System.IO.DirectoryInfo] (Get-Item $termsFolderPath)).GetFiles()
#looping through all files
ForEach($file in $files)
       {
              $reader = new-object System.IO.StreamReader($file.FullName)
      
              #output variables
              $alltermsadded = $false
              $errormessage = ""
       #import the termset file
       $manager.ImportTermSet($group, $reader, [ref] $alltermsadded, [ref] $errormessage)
}

Thanks!

Enjoy Reading J

As usual any comment / suggestions / feedback / questions always welcome :) 

Saturday, 5 August 2017

SharePoint 2013 – Retract Solution – Access Denied error

Hi All,

Today, new error and solution. I’ll explain the error which we received while retracting farm solution and the solution for it.

Background: We have SharePoint 2013 farm and were retracting solution, we were using chrome browser. In browser in two tabs our site was open and in one tab central admin. When we are trying to retract solution through central admin we were getting an “Access Denied” error. We are logged in with user having Administrator rights so it seems not to be user permission issue.
It was very small fix but thought to share, can save your time.

Error and Stack Trace:
Access denied.  Only machine administrators are allowed to create administration service job definitions of type: Microsoft.SharePoint.Administration.SPSolutionDeploymentJobDefinition, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.
Application error when access /_admin/RetractSolution.aspx, Error=Access denied.  Only machine administrators are allowed to create administration service job definitions of type: Microsoft.SharePoint.Administration.SPSolutionDeploymentJobDefinition, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c.   at Microsoft.SharePoint.Administration.SPAdministrationServiceJobDefinition..ctor(String name, SPService service, SPServer server, SPJobLockType lockType)     at Microsoft.SharePoint.Administration.SPSolutionDeploymentJobDefinition..ctor(String solutionName, Guid solutionId, UInt32 lcid, SPTimerService service, SPCompatibilityRange compatibilityRange)     at Microsoft.SharePoint.Administration.SPSolutionLanguagePack.CreateSolutionDeployTimerJob(DateTime...              e4a5099e-e182-6064-8575-d8b087e7d93c
General                             8nca      Medium             ... dt, Collection`1 webApplications, SPSolutionDeploymentJobType jobType, Boolean globalInstallDlls, Boolean force, Boolean isRestore, SPCompatibilityRange compatibilityRange)     at Microsoft.SharePoint.ApplicationPages.SolutionPageBase.CreateDeploymentJob(Boolean deploy, String strSelectedWeb, Boolean globalInstall, DateTime dt, Boolean localDeployment)     at Microsoft.SharePoint.ApplicationPages.RetractSolutionPage.BtnSubmit_Click(Object sender, EventArgs e)     at System.Web.UI.WebControls.Button.OnClick(EventArgs e)     at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)     at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)     at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsy...              e4a5099e-e182-6064-8575-d8b087e7d93c

Solution:

It seems to be weird error. No user permission issue.

We googled a lot and then got below article related to same issue but not exact one.


In above article not exact issue mentioned but at least we got an idea. We have closed the browser, open the central admin again with run as administrator option, tried again it worked like charm.

Thanks!

Enjoy Reading J

As usual any comment / suggestions / feedback / questions always welcome :)

Thursday, 27 July 2017

SharePoint Online / Office 365 - Exporting All the Terms from Particular TermSet in .CSV file using CSOM and console application

Hi All,

In this article I’ll explain how to export term sets in .CSV file using CSOM and console application.  


There are multiple approaches to export the terms from given TermSet either using PowerShell + CSOM or using CSOM in console application. In one of my previous article "SharePointOnline / Office 365 : Exporting All The Terms From Particular TermSet In .csvfile Using CSOM & PowerShell" I explained how to export the TermSet using CSOM + PowerShell. 

In this article I’ll go through step by step for exporting TermSet using CSOM in console application.

There is no as such difference in both the approaches but if we want to make it more configurable (like configuration in .config file, for ex. – TermStore name or specific TermSet name etc. ) then Console Application approach is preferable.

I have my trial Office 365 account and term store manager page looks like, created three terms (IT, HR and Finance) in OOB term set “Department” under “People” group:

So in our console application we will export the above three terms created under “Department” term set in “People” group in default term store (since there only one termstore).

Step 1: Get the required details from config file (App.config) and connecting to Office 365:

In last article “Office365 / SharePoint Online - Connecting Office 365 / SharePoint Online Site UsingCSOM (Client Object Model)” I have given detailed steps to connect Office 365 through CSOM and Console Application. Please have a look once. Following is the code snippet for this step:

       #region Site Details - Read the details from config file
            string siteURL = ConfigurationManager.AppSettings["siteURL"];
            string userName = ConfigurationManager.AppSettings["userName"];
            string password = ConfigurationManager.AppSettings["password"];
            //Path where we need to create the .CSV file
            string csvFilePath = ConfigurationManager.AppSettings["csvfilepath"];
       #endregion

#region Connect To O365

            //Create the client context object and set the credentials
//Create the client context object and set the credentials
              ClientContext clientContext = new ClientContext(siteURL);
       SecureString securePassword = new SecureString();

foreach (char c in password.ToCharArray())    
              securePassword.AppendChar(c);

                     clientContext.Credentials = new   
                     SharePointOnlineCredentials(userName, securePassword);
        #endregion

Step 3: Get the Terms from respective TermSet : To read the Terms from respective TermSet we need to get the reference for following objects

1.       TaxonomySession : This object is the initial point for all taxonomy operations. Get reference to the TaxonomySession object as

TaxonomySession taxonomysession = TaxonomySession.GetTaxonomySession(clientContext);

2.       TermStore : Get reference to default TermStore object. Once we have TaxonomySession class, we will get the default term store as  

TermStore termStore = taxonomysession.GetDefaultSiteCollectionTermStore();

3.       TermGroupCollection : We will fetch all the groups (TermGroupCollection) from TermStore object as
                TermGroupCollection groupCollection = termStore.Groups;
                clientContext.Load(groupCollection);
                clientContext.ExecuteQuery();

4.       TermGroup : Then get the reference to the TermGroup object in which our TermSet is created, here we are fetching the terms from the term set which is created under group “People” as

TermGroup termGroup = groupCollection.GetByName("People");
clientContext.Load(termGroup);
clientContext.ExecuteQuery();

5.       TermSet : From termGroup object we will read our “Department” term set as

TermSet termSet = termGroup.TermSets.GetByName("Department");
clientContext.Load(termSet);
clientContext.ExecuteQuery();

6.       TermCollection : We have our term set ready, get all terms in it using TermCollection object as

TermCollection departmentTerms = termSet.Terms;
                       clientContext.Load(departmentTerms);
                       clientContext.ExecuteQuery();

Step 4: Write terms to .CSV file : Since now we have all “Department” terms, we will write them to .CSV file.  To write into .CSV file we will need array of string and we will use Syste.IO.File object as
ArrayList termsArrayList = new ArrayList(departmentTerms.Count);

              foreach (Term term in departmentTerms)
              {
                 termsArrayList.Add(term.Name);
              }

                             //Writing to .CSV file as path specified in .config file.
System.IO.File.WriteAllLines(csvFilePath,           (string[])termsArrayList.ToArray(typeof(string)));


Complete Code:

using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Taxonomy;
using System;
using System.Collections;
using System.Configuration;
using System.Security;

namespace CSOM_ExportTermSets
{
    class Program
    {
        static void Main(string[] args)
        {
            #region Site Details - Read the details from config file
            string siteURL = ConfigurationManager.AppSettings["siteURL"];
            string userName = ConfigurationManager.AppSettings["userName"];
            string password = ConfigurationManager.AppSettings["password"];
            //Path where we need to create the .CSV file
            string csvFilePath = ConfigurationManager.AppSettings["csvfilepath"];
            #endregion

            #region ConnectTo O365

            //Create the client context object and set the credentials
            ClientContext clientContext = new ClientContext(siteURL);
            SecureString securePassword = new SecureString();

            foreach (char c in password.ToCharArray()) securePassword.AppendChar(c);

clientContext.Credentials = new SharePointOnlineCredentials(userName, securePassword);

            #endregion

            #region Get the Terms

TaxonomySession taxonomysession = TaxonomySession.GetTaxonomySession(clientContext);
    
            if (taxonomysession != null)
            {
 TermStore termStore = taxonomysession.GetDefaultSiteCollectionTermStore();
                if (termStore != null)
                {
                    TermGroupCollection groupCollection = termStore.Groups;
                    clientContext.Load(groupCollection);
                    clientContext.ExecuteQuery();

                    TermGroup termGroup = groupCollection.GetByName("People");
                    TermSet termSet = termGroup.TermSets.GetByName("Department");

                    clientContext.Load(termGroup);
                    clientContext.Load(termSet);
                    clientContext.ExecuteQuery();

                    TermCollection departmentTerms = termSet.Terms;
                    clientContext.Load(departmentTerms);
                    clientContext.ExecuteQuery();

                    ArrayList termsArrayList = new ArrayList(departmentTerms.Count);

                    foreach (Term term in departmentTerms)
                    {
                        termsArrayList.Add(term.Name);
                    }

                    //Writting to .CSV file as path specified in .config file.
System.IO.File.WriteAllLines(csvFilePath, (string[])termsArrayList.ToArray(typeof(string)));

Console.WriteLine("Terms are written in .CSV file. Please hit the any key to exit the console");
                    Console.ReadKey();
                }//if (termStore != null)
            }//if (taxonomysession != null)
            #endregion
        }//main
    }//cs
}//ns

Thanks!

Enjoy Reading :)

As usual any feedback / query / suggestions are most welcome!!!