• Create a SharePoint Application Pool using PowerShell

    As you may know there isn't an out of the box PowerShell cmdlet available in SharePoint 2010 or 2013 that can be used to create an Application Pool for a Web Application, New-SPServiceApplicationPool (http://technet.microsoft.com/en-us/library/ff607595(v=office.15).aspx) is available however this can only be used to create an Application Pool for a Service Application.

    A customer recently asked me to help them to re-configure one of their Web Applications to use a new Application Pool, I put this script together to facilitate this. The script performs the following actions:

    • Creates a new Application Pool
    • Associates the new Application Pool with an existing Web Application

    Three variables need to be updated prior to running the script:

    $WebAppURL is the URL of the Web App to change the Application Pool of.
    $NewAppPoolName is the name of the name Application Pool that will be created.
    $NewAppPoolUserName is the user account that the Application Pool will run under the context of.

    The script will prompt for the credentials of the account specified in $NewAppPoolUserName. This account should be registered as a Managed Account in SharePoint prior to executing the script - New-SPManagedAccount: http://technet.microsoft.com/en-us/library/ff607831(v=office.15).aspx

    asnp *SharePoint* -ErrorAction SilentlyContinue
    $WebAppURL = "http://WebApp"
    $NewAppPoolName = "NewAppPool"
    $NewAppPoolUserName = "contoso\apppool"

    $Farm = Get-SPFarm
    $Service = $Farm.Services | where {$_.TypeName -eq "Microsoft SharePoint Foundation Web Application"}
    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString
    $NewAppPool = New-Object Microsoft.SharePoint.Administration.SPApplicationPool($NewAppPoolName,$Service)
    $NewAppPool.CurrentIdentityType = "SpecificUser"
    $NewAppPool.Username = $NewAppPoolUserName
    $NewAppPool.SetPassword($Password)
    $NewAppPool.Provision()
    $NewAppPool.Update($true)

    $NewAppPool = $Service.ApplicationPools[$NewAppPoolName]
    $WebApp = Get-SPWebApplication $WebAppURL
    $WAAppPool = $WebApp.ApplicationPool = $NewAppPool
    $WebApp.Update()
    $WebApp.ProvisionGlobally()


    Brendan Griffin - @brendankarl

  • Office 365 - Exporting Site Collection Search Configuration using CSOM with PowerShell

    Chris O'Brien has a fantastic Blog post - Using CSOM in PowerShell Scripts with Office 365: http://www.sharepointnutsandbolts.com/2013/12/Using-CSOM-in-PowerShell-scripts-with-Office365.html. One of the examples that he provides is how to import search configuration from an XML file, this is a new feature in SharePoint 2013 that is documented here - http://technet.microsoft.com/en-us/library/jj871675(v=office.15).aspx.

    I've put together a PowerShell script that can be used to export the search configuration, using this along with Chris's script is a great way to copy Search configuration between Site Collections.

    Three variables need to be updated prior to running the script (highlighted), $User is the username of a tenant administrator, $Site is the URL of the Site within the tenant to export the search configuration from and $Schema is the location of the file to write the configuration to.

    #Please install the SharePoint client components SDK - http://www.microsoft.com/en-us/download/details.aspx?id=35585 prior to running this script.

    #Specify tenant admin, site URL and scope to export from
    $User = "admin@tenant.onmicrosoft.com"
    $SiteURL = https://tenant.sharepoint.com/sites/site
    $Scope = "SPSite"
    $Schema = "D:\SearchSchema.XML"

    #Add references to SharePoint client assemblies and authenticate to Office 365 site - required for CSOM
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Search.dll"

    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)

    #Export search configuration
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $Context.Credentials = $Creds
    $Owner = New-Object Microsoft.SharePoint.Client.Search.Administration.SearchObjectOwner($Context,$Scope)
    $Search = New-Object Microsoft.SharePoint.Client.Search.Portability.SearchConfigurationPortability($Context)
    $SearchConfig = $Search.ExportSearchConfiguration($Owner)
    $Context.ExecuteQuery()
    $SearchConfig.Value > $Schema


    Brendan Griffin - @brendankarl

  • Office 365 - Automating the Creation of a Design Manager Package using CSOM with PowerShell

    One of the really cool features in SharePoint 2013 is the Design Manager, further information on this feature can be found here: Overview of Design Manager in SharePoint 2013 - http://msdn.microsoft.com/en-us/library/jj822363.aspx.

    Design Manager provides the ability to export a Design Manager Package so that customizations can be easily copied to another Site Collection and re-used - potentially saving a lot of time and hassle, the package itself is a sandbox solution using the WSP file format. A screenshot of the option can be found below:

    Wouldn't it be cool if you could automate the creation of a Design Manager Package using PowerShell? Below is a PowerShell script that uses CSOM to perform this very task! The resultant package is saved to a local drive for re-use.

    The three highlighted variables need to be updated. $Username is the username of an administrator of the Site Collection, $Site is the URL of the Site Collection and $DestinationDir is the local directory to save the exported package to.

    #Please install the SharePoint client components SDK - http://www.microsoft.com/en-us/download/details.aspx?id=35585
    $Username = "admin@tenant.onmicrosoft.com"
    $Site = "https://tenant.sharepoint.com/sites/site"
    $DestinationDir = "D:\Downloads\"

    #Add references to SharePoint client assemblies and authenticate to Office 365 site
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Publishing.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($Site)
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Username,$Password)
    $Context.Credentials = $Creds

    $SC = $Context.Site
    $Context.Load($SC)
    $Context.ExecuteQuery()

    $RootWeb = $SC.RootWeb
    $Context.Load($RootWeb)
    $Context.ExecuteQuery()

    $DP = [Microsoft.SharePoint.Client.Publishing.DesignPackage]::ExportEnterprise($Context,$SC,$False)
    $Context.ExecuteQuery()

    #Download Design Package
    $Package =  $SC.ServerRelativeUrl + "/_catalogs/Solutions/" + $RootWeb.Title + "-1.0.wsp"
    $Destination =  $DestinationDir + $RootWeb.Title + "-1.0.wsp"
    $FileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($Context,$Package)
    $WriteStream = [System.IO.File]::Open($Destination,[System.IO.FileMode]::Create);
    $FileInfo.Stream.CopyTo($WriteStream)
    $WriteStream.Close();

    Brendan Griffin - @brendankarl

  • Office 365 - Automating the Creation of Managed Metadata Groups, Term Sets and Terms using CSOM with PowerShell

    I've previously written a Blog post on how to output MMS Term Sets and Terms using CSOM - http://blogs.technet.com/b/fromthefield/archive/2014/03/03/office-365-output-managed-metadata-term-sets-and-terms-using-csom.aspx. This next script example can be used to automate the creation of MMS Groups, Term Sets and Terms. The only reason that I wrote this script was for an excuse to improve my understanding of the CSOM API for MMS!

    The script itself takes input in the form of an XML file, example below:

    The script will create the MMS Groups, Term Sets and Terms contained within the XML file. I have attached an example XML file for reference.

    Three variables need to be updated prior to running the script (highlighted), $User is the username of a tenant administrator, $Site is the URL of any Site within the tenant - this is simply used to bind to the Managed Metadata Service and $Import which is the location of the XML input file.

    #Please install the SharePoint client components SDK - http://www.microsoft.com/en-us/download/details.aspx?id=35585 prior to running this script.

    #Specify tenant admin and URL
    $User = admin@tenant.onmicrosoft.com
    $Site = "https://tenant.sharepoint.com/sites/CSOM"
    [XML]$Import = Get-Content "D:\Example.xml"

    #Add references to SharePoint client assemblies and authenticate to Office 365 site - required for CSOM
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll"
    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString

    #Bind to MMS
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($Site)
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)
    $Context.Credentials = $Creds
    $MMS = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($Context)
    $Context.Load($MMS)
    $Context.ExecuteQuery()

    #Retrieve Term Stores
    $TermStores = $MMS.TermStores
    $Context.Load($TermStores)
    $Context.ExecuteQuery()

    #Bind to Term Store
    $TermStore = $TermStores[0]
    $Context.Load($TermStore)
    $Context.ExecuteQuery()

    Foreach ($GroupName in $Import.Groups.Group)
    {
    #Create Groups
    $Group = $TermStore.CreateGroup($GroupName.Name,[System.Guid]::NewGuid().toString())
    $Context.Load($Group)
    $Context.ExecuteQuery()
        Foreach ($TermSetName in $GroupName.TermSets)
            {
            #Create Term Sets
            $TermSet = $Group.CreateTermSet($TermSetName.Name,[System.Guid]::NewGuid().toString(),1033)
            $Context.Load($TermSet)
            $Context.ExecuteQuery()
            Foreach ($TermName in $TermSetName.Terms.Term)
                {
                #Create Terms
                $TermAdd = $TermSet.CreateTerm($TermName,1033,[System.Guid]::NewGuid().toString())
                $Context.Load($TermAdd)
                $Context.ExecuteQuery()
                }
            }
    }

    Below is an example of how the Term Store will look after running the script with Example.XML file:

    Brendan Griffin - @brendankarl

  • SharePoint 2013 - December CU - Exception: No mapping between account names and security IDs was done

    I was recently helping a colleague to troubleshoot an issue that he was running into whilst deploying the December 2013 CU for SharePoint 2013, the following error was being logged in the upgrade log.

    Exception: No mapping between account names and security IDs was done 00000000-0000-0000-0000-000000000000
    03/03/2014 18:46:19.17 PSCONFIG (0x0EA8) 0x0BCC SharePoint Foundation Upgrade SPUpgradeSession ajxnm ERROR    at Microsoft.Office.Server.Utilities.WindowsSecurity.LookupAccountName(String accountName, String& domainName, SID_NAME_USE& use)     at Microsoft.Office.Server.Utilities.WindowsSecurity.GetNT4AccountName(String name)     at Microsoft.Office.Server.Data.SqlServerManager.GrantLogin(String user)     at Microsoft.Office.Server.Search.Administration.SearchDatabase.GrantAccess(String username, String role)     at Microsoft.Office.Server.Search.Administration.SearchDatabase.SynchronizeAccessRules(SearchServiceApplication searchApp)     at Microsoft.Office.Server.Search.Administration.SearchServiceApplication.SynchronizeDatabases()     at Microsoft.Office.Server.Search.Upgrade.SearchAdminDatabaseSequence.PostUpgrade()     at Microsoft.SharePoint.Upgrade.SPUpgradeSession.Upgrade(Object o, Boolean bRecurse)


    I had a look to see what the Microsoft.Office.Server.Search.Administration.SearchDatabase.SynchronizeAccessRules() method was doing, it turns out that this method (amongst other things) validates each user/group that is added as an Administrator to the Search Service Application. If the user account or group no longer exists the lookup fails which causes the above exception and the upgrade process to fail. The fix is fairly simple - remove any users or groups from the permissions list of the Search Service Application within Central Administration that no longer exist. I have written a PowerShell script that outputs all of the account types that are verified by the method, whilst the issue could be with one of the other three types of accounts that the method validates it's not likely as Search or the Farm will be seriously broken if they configured to use an account that no longer exists!

    • Search Service Application Administrators
    • Search Service Process Identity
    • Search Service Application Pool
    • Timer Service Identity

    The script makes the presumption that you have a single Search Service Application in the farm.

    asnp *sharepoint* -ea SilentlyContinue
    $SSA = Get-SPEnterpriseSearchServiceApplication
    $SSAAdmins = $SSA.GetAdministrationAccessControl().AccessRules.Name
    $SearchService = (Get-SPEnterpriseSearchService).ProcessIdentity
    $AppPool = $SSA.ApplicationPool.ProcessAccountName
    $TimerService = (Get-SPFarm).TimerService.ProcessIdentity.UserName
    Write-Host SSA Admins: $SSAAdmins -ForegroundColor Green
    Write-Host Search Service: $SearchService -ForegroundColor Green
    Write-Host App Pool: $AppPool -ForegroundColor Green
    Write-Host Timer Service: $TimerService -ForegroundColor Green



    Brendan Griffin - @brendankarl