Fix SharePoint Quick Launch Links using PowerShell


A lot of times when I’m working on an environment for a client, I come across a situation where I’m in need of a way to quickly update links – usually because people have entered them as an absolute URL (e.g. http://intranet/pages/somepage.aspx) instead of a relative URL (e.g. /pages/somepage.aspx).

Usually when I run across a problem like this, I actually get excited – because these are great opportunities to use our buddy PowerShell! Unfortunately, there aren’t many examples out there of how to use PowerShell to manipulate SharePoint Navigation objects. Hopefully this blog post will be helpful for someone looking to do the same thing I needed to do…

Here’s how it all comes together – and if you don’t want to understand how it works just skip to the end and copy/paste the code :).

Getting the Web Object

The first thing we have to do in order to even begin to work on SharePoint Navigation is to retrieve an SPWeb object. To do this, it’s pretty simple – just run the following code, which will store the Microsoft.SharePoint.SPWeb into the $SPWeb variable:

$SPWeb = Get-SPWeb $Web

Getting the Web.Navigation.QuickLaunch Object

After we’ve retrieved that object, if you use Get-Member to view the Methods and Properties, you’ll quickly notice that the Navigation Property has a QuickLaunch property within it. This is exactly what we want. We can now start to use the ForEach-Object cmdlet to actually show us everything beneath the SPWeb.Navigation.QuickLaunch. Or more specifically, we can use an IF statement to make sure we only grab the appropriate URLs – that is, only ones matching the string we want to replace. Here’s the code snippet:

$SPWeb.Navigation.QuickLaunch | ForEach-Object {
    if($_.Url -match $FindString){
        $linkUrl = $_.Url
        Write-Host "Updating $linkUrl with new URL"
        $_.Url = $_.Url.Replace($FindString,$ReplaceString)
        $_.Update()
    }

Pretty cool, so essentially we just say if the URL matches the string we’re looking for, then go ahead and tell us it’s working on it – then update it, replacing the value of the FindString variable with the value of the ReplaceString variable. Both of these variables are actually mandatory parameters, you’ll see that part at the end… Finally, run the Update() method on each one to actually commit the changes to the server.

All done right? No, we can’t forget about the children!

Fixing the Child links

So far the code we’ve seen will only touch the parent links, but each link also has a Children node. We can simply use the same code as before, except this time we’ll run it against the $_.Children property of each link node.

Here’s how that looks:

$_.Children | ForEach-Object {
        if($_.Url -match $FindString){
            $linkUrl = $_.Url
            Write-Host "Updating $linkUrl with new URL"
            $_.Url = $_.Url.Replace($FindString,$ReplaceString)
            $_.Update()
        }
    }

And now, if we put it all together, you’ll see that we have a nice, clean function to do a quick find and replace of navigation links on the quick launch of a single SharePoint Web. I’ve called the function Repair-SPLeftNavigation, and it has 3 required parameters – Web, FindString and ReplaceString:

function Repair-SPLeftNavigation {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)][System.String]$Web,
[Parameter(Mandatory=$true)][System.String]$FindString,
[Parameter(Mandatory=$true)][System.String]$ReplaceString
)
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
$SPWeb = Get-SPWeb $Web
$SPWeb.Navigation.QuickLaunch | ForEach-Object {
    if($_.Url -match $FindString){
        $linkUrl = $_.Url
        Write-Host "Updating $linkUrl with new URL"
        $_.Url = $_.Url.Replace($FindString,$ReplaceString)
        $_.Update()
    }
    $_.Children | ForEach-Object {
        if($_.Url -match $FindString){
            $linkUrl = $_.Url
            Write-Host "Updating $linkUrl with new URL"
            $_.Url = $_.Url.Replace($FindString,$ReplaceString)
            $_.Update()
        }
    }
}
$SPWeb.Dispose()
}#endFunction

To run this bad boy, simply dot-source the function and then call it like a cmdlet – for example:

. .\Repair-SPLeftNavigation.ps1
Repair-SPLeftNavigation -Web http://sp2013 -FindString 'http://sp2010' -ReplaceString 'http://sp2013'

If you needed to run this on multiple site collections or even web applications, you could simply use the native ForEach-Object cmdlet in conjunction with this function to accomplish that goal.

Cheers!
RD

Advertisements

5 thoughts on “Fix SharePoint Quick Launch Links using PowerShell

  1. Joshua Loomis

    My situation would likely be helped by a script very similar to this one. In my case, I am trying to replace a URL ‘/site/subsite’ with a URL ‘/new_parent/site/subsite.’ However, some of the links are already correct, so it seems like this script would potentially break the good links as they also contain the $findString content.

    How would I modify this script to find strings that begin with $FindString, rather than contain the string? Thanks!

    • Ryan Dennis

      The -match comparison operator is a Regular Expression operator, so you can put a “^” at the beginning for this. Example would be:

      $str = "string"
      $str -match "^tring" #Should return False
      $str -match "^string" #Should return True

  2. Tino (@tnofam)

    If I wanted to add a link that isn’t there currently what would the command for that be?

    I have a script that I’m going to use to create sub sites. I was hoping to add to it something similar to what you posted to add a link in the left navigation on the parent site. Awesome post by the way.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s