How to Update Navigation (Quick Launch and Top NavigationBar) URLs in SharePoint 2010 using PowerShell CSOM


Sathish Nadarajan
SharePoint MVP
Published On :   28 Dec 2017
Visit Count
Today :  1    Total :   2053



During the Migration from SP2010 to SP2016, if the Quick Launch or the Top Navigation of the Source Sites were having the Full URL, (e.g., https://mySP2010Site.com/Sites/SiteCollection/MyList/Forms/AllItems.aspx), then any Migration tool will migrate the Navigation URLs as it is. Hence, in the Target, if we click on the Link, then it will go to the Source Link, not the Target Link. For that, before migrating the content, we can update the URLs with relating Path. i.e., /sites/sitecollection/MyList/Forms/AllItems.aspx. By doing this, when we migrate, the Target will also have the relative path which will be the corresponding target site collection’s path. Though this may not work for different web applications/different tenants, but somehow this will fix the initial problem statement.

Let us see the detailed script, which will update the Quick Launch and the Navigation Bars using PowerShell CSOM in SP2010 Environment. The below script, I wrote it for two levels only. We can make the update statement as a recursive method, so that it will update any level of the Links.

 # Update the Navigation (QuickLaunch and TopNavigationBar) URLs
 
 ##================================================================================================
 ## Description	: 
     #Update the Navigation (QuickLaunch and TopNavigationBar) URLs
  
 ## Author		: Sathish Nadarajan
 ## Date			: 
 ##================================================================================================
 
 # ============================================ Setup Input Paths ================================= 
 
 cls
 
  
 $Host.UI.RawUI.WindowTitle = "-- Update QuickLaunch and TopNavigationBar URLs--"
 
 $StartDate = Get-Date
 Write-Host -ForegroundColor White "------------------------------------"
 Write-Host -ForegroundColor White "| Update QuickLaunch and TopNavigationBar URLs |"
 Write-Host -ForegroundColor White "| Started on: $StartDate |"
 Write-Host -ForegroundColor White "------------------------------------"
 
 $LogTime = Get-Date -Format yyyy-MM-dd_hh-mm
 
 ################# Set the Current Path as Execution Path ####################
 
 $scriptBase = split-path $SCRIPT:MyInvocation.MyCommand.Path -parent
 Set-Location $scriptBase
 
 ############# set the Error Preference ################
 
 $ErrorActionPreference = "SilentlyContinue"
 
 # Create Log File Folder
 if(!(TEST-PATH ".\Logs-$LogTime")) 
 {
    NEW-ITEM ".\Logs-$LogTime" -type Directory
 }
 
 # Assign the Log and Progress Files
 $TranscriptFile = ".\Logs-$LogTime\UpdateNavigationLinks.Transcript.rtf"
 
 try{
   stop-transcript|out-null
 }
 catch [System.InvalidOperationException]{}
 
 start-transcript $TranscriptFile
 
 
 function AddCSOM(){
      #Load SharePoint client dlls 
      $a = [System.Reflection.Assembly]::LoadFile(    "$scriptBase\ClientLibraries\Microsoft.SharePoint.Client.dll") 
      $ar = [System.Reflection.Assembly]::LoadFile(    "$scriptBase\ClientLibraries\Microsoft.SharePoint.Client.Runtime.dll") 
      
      if( !$a ){
          $a = [System.Reflection.Assembly]::LoadWithPartialName(        "Microsoft.SharePoint.Client")
      }
      if( !$ar ){
          $ar = [System.Reflection.Assembly]::LoadWithPartialName(        "Microsoft.SharePoint.Client.Runtime")
      }
      
      if( !$a -or !$ar ){
          throw         "Could not load Microsoft.SharePoint.Client.dll or Microsoft.SharePoint.Client.Runtime.dll"
      }
      
      
      #Add overload to the client context.
      #Define new load method without type argument
      $csharp =     "
       using Microsoft.SharePoint.Client;
       namespace SharepointClient
       {
           public class PSClientContext: ClientContext
           {
               public PSClientContext(string siteUrl)
                   : base(siteUrl)
               {
               }
               // need a plain Load method here, the base method is a generic method
               // which isn't supported in PowerShell.
               public void Load(ClientObject objectToLoad)
               {
                   base.Load(objectToLoad);
               }
           }
       }"
      
      $assemblies = @( $a.FullName, $ar.FullName,     "System.Core")
      #Add dynamic type to the PowerShell runspace
      Add-Type -TypeDefinition $csharp -ReferencedAssemblies $assemblies
 }
 
 
 AddCSOM
 
 $credentials = Get-Credential
 
 #Get inthe Input CSV File
 $SubSiteURLCSV = $scriptBase + "\" + "SubSiteURLs.csv"
 
  
 
 cls
 
 $originalURL = " https://mySP2010Site.com/"
 
 #Read and Iterate through all the Sites Given in the SubSiteURLs.CSV
 import-csv $SubSiteURLCSV | where{
     Write-Host "Processing the Site : " $_.SubSiteURL -ForeGroundColor Green
                 
     $context = New-Object SharepointClient.PSClientContext($_.SubSiteURL)
     $totalDocLibSize =0
     
     $totalListSize=0
     $totalWebSize=0
      
     $context.Credentials = $credentials
     
     #Load the basic information about the web and site
     $context.Load($context.Web)
     $context.Load($context.Web.Navigation.QuickLaunch)
     $context.Load($context.Web.Navigation.TopNavigationBar)
     $context.Load($context.Site)
     $context.Load($context.Web.Lists)
     $context.ExecuteQuery()
     
     
     
     ############### BEGIN QUICK LAUNCH ################################
     Write-Host "Processing the Quick Launch (Left Navigation)"
     foreach($quickLaunch in $context.Web.Navigation.QuickLaunch)
     {
         $context.Load($quickLaunch)
         $context.Load($quickLaunch.Url)
         $context.Load($quickLaunch.Children)
         $context.ExecuteQuery()
         
         ############### PARENT LINKS #################################
         if($quickLaunch.Url -like  ('*'+$originalURL+'*'))
         {
             Write-Host "Updating the Link : " $quickLaunch.Title
             $temp = $quickLaunch.Url
             $temp = $temp.Replace($originalURL, "")
             
             $quickLaunch.Url = $temp
             $quickLaunch.Update()
             $context.Load($quickLaunch)
             $context.ExecuteQuery()
         }
         
         ########### FIRST LEVEL CHILD LINKS ##########################
         foreach($quickLink in $quickLaunch.Children)
         {
             $context.Load($quickLink)
             $context.Load($quickLink.Url)
             $context.ExecuteQuery()
         
             if($quickLink.Url -like ('*'+$originalURL+'*'))
             {
                 Write-Host "Updating the Child Link : " $quickLink.Title
                 $temp = $quickLink.Url
                 $temp = $temp.Replace($originalURL, "")
                 
                 $quickLink.Url = $temp
                 $quickLink.Update()
                 $context.Load($quickLink)
                 $context.ExecuteQuery()
             }
         }        
     }
     
     ############ END QUICK LAUNCH ####################################
     
     ############### BEGIN TOPNAVIGATIONBAR ################################
     Write-Host "Processing the NavigationBar (Top Navigation)"
     
     foreach($quickLaunch in $context.Web.Navigation.TopNavigationBar)
     {
         $context.Load($quickLaunch)
         $context.Load($quickLaunch.Url)
         $context.Load($quickLaunch.Children)
         $context.ExecuteQuery()
         
         ############### PARENT LINKS #################################
         if($quickLaunch.Url -like  ('*'+$originalURL+'*'))
         {
             Write-Host "Updating the Top Link : " $quickLaunch.Title
             $temp = $quickLaunch.Url
             $temp = $temp.Replace($originalURL, "")
             
             $quickLaunch.Url = $temp
             $quickLaunch.Update()
             $context.Load($quickLaunch)
             $context.ExecuteQuery()
         }
         
         ########### FIRST LEVEL CHILD LINKS ##########################
         foreach($quickLink in $quickLaunch.Children)
         {
             $context.Load($quickLink)
             $context.Load($quickLink.Url)
             $context.ExecuteQuery()
         
             if($quickLink.Url -like ('*'+$originalURL+'*'))
             {
                 Write-Host "Updating the top Child Link : " $quickLink.Title
                 $temp = $quickLink.Url
                 $temp = $temp.Replace($originalURL, "")
                 
                 $quickLink.Url = $temp
                 $quickLink.Update()
                 $context.Load($quickLink)
                 $context.ExecuteQuery()
             }
         }        
     }
     
     ############ END QUICK LAUNCH ####################################
      
 }
 
 Write-Host "Process Completed..  Press Enter to Exit" -ForeGroundColor Green
 
  try{
   stop-transcript|out-null
 }
 catch [System.InvalidOperationException]{}       
 

Happy Coding,

Sathish Nadarajan.

Categories