2

Consider the following PowerShell script to update a Term Set 'Global Navigation' which is pinned throughout the farm:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ea SilentlyContinue

Write-Host "Updating Global Navigation for the entire farm"
$url = 'http://spserver:2013'
$termStoreName = 'Managed Metadata Service'
$termGlobalGroupName = 'Global Navigation'
$termSetName = 'Global Navigation'

function Get-NavStore() {
    $web = Get-SPWeb $url
    $site = $web.Site
    $taxSession = Get-SPTaxonomySession -Site $site
    return $taxSession.TermStores[$termStoreName]
}

function Get-NavTerms() {
    $termStore = Get-NavStore
    $termGroup = $termStore.Groups[$termGlobalGroupName]
    $termSet = $termGroup.TermSets[$termSetName]
    return $termSet.Terms
}

foreach ($site in Get-SPSite -Limit all) {
    $navTerms = Get-NavTerms
    $taxSession = Get-SPTaxonomySession -Site $site
    $termStore = $taxSession.TermStores[$termStoreName]
    $name = "Site Collection - " + $site.HostName + $site.ServerRelativeUrl.Replace('/','-').TrimEnd('-')
    $termGroup = $termStore.Groups | ? {$_.Name -eq $name}
    if ($termGroup.Count -lt 1) {
        Write-Host "Skipping:" $site.Url "(No group found matching '$name')"
    } else {
        Write-Host "Found group:" $termGroup.Name
        $termSets = $termGroup.TermSets | ? {$_.Name -match "Navigation"}
        if ($termSets.Count -lt 1) {
            Write-Host "No term sets found with the name 'Navigation'"
        } elseif ($termSets.Count -gt 1) {
            Write-Host "Too many term sets found with the name 'Navigation'"
        } else {
            $termSet = $termSets[0]
            $terms = $termSet.Terms
            foreach ($t in $terms) {
                Write-Host "Deleting" $t.Name
                $t.Delete()
            }
            $termStore.CommitAll()

            foreach ($t in $navTerms) {
                Write-Host "Pinning" $t.Name
                $termSet.ReuseTermWithPinning($t) | out-null
            }
            $termSet.CustomSortOrder = $termSet.CustomSortOrder
            $termStore.CommitAll()
        }
    }
}

This script works, however I have to run it twice. This is because the first time it runs through I receive the following error when trying to ReuseTermWithPinning:

Exception calling "ReuseTermWithPinning" with "1" argument(s): "Terms can not be shared multiple times in the same term set"
At line:49 char:17
+                 $termSet.ReuseTermWithPinning($t) | out-null
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : TermStoreOperationException

I run it again, and I do not get this error as it doesn't need to Delete any nodes -- simply Reuse them. Its as if when I run the .CommitAll() it does not actually commit the changes and I'm trying to pin terms that are still there. It only commits the data when exiting out of the script. I have tried to break out the logic differently and have tried to reload the Managed Metadata objects but I still get the same errors.

1

I thought I would provide an update on how I achieved a better overall solution. I took the same logic within the PowerShell script and created a custom Visual Studio solution that has an application page with a button that syncs the terms and outputs a report.

The only other issue I ran into with that was with the hidden Taxonomy feature not being activated on team sites.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.