Wednesday, 23 March 2011

Managing Quick Launch navigation in SharePoint Foundation using PowerShell

Quick Launch (left-hand navigation) functionality in SharePoint Foundation can be fairly limited if you’re looking to add or standardise links across multiple sites. Unlike SharePoint Server 2010, there are no facilities available to inherit navigation items from parent sites or show items below the current site.

One method of managing navigation items on sites without reverting to code-based solutions would be to use PowerShell. In this article I will run through the basics of moving and creating new Quick Launch headings and links, and at the end provide a couple of scripts that allow you to export Quick Launch items from one site and import them into another site.

Note that these scripts will only work on SharePoint Foundation sites – or sites in SharePoint Server 2010 where the “SharePoint Server Publishing Infrastructure” site collection feature is not activated. I have covered managing SharePoint Server 2010 Quick Launch navigation on site collections with the Publishing Infrastructure feature activated in this article.

First, we need to get the Web and QuickLaunch objects and assign them to variables. For this example, I am modifying the root site of a site collection created at http://portal/sites/foundation:

$web = Get-SPWeb http://portal/sites/foundation
$qlNav = $web.Navigation.QuickLaunch

If you would like to see a list of headings already created on the site with their node ID’s, type the following:

$qlNav | select Title, ID


To make changes to a heading, we need to assign it to a variable first. There are methods to do this with the ID and link URL, but I prefer to use the heading Title as it’s more user friendly and will be the same across each site. For example, type this command to get the Libraries heading:

$qlHeading = $qlNav | where { $_.Title -eq "Libraries" }

If there is more than one heading with the same name, you will need to type the following command to select the correct one. Changing the number in the square brackets will be how you do this, with 0 being the first heading, 1 the second heading, 2 the third heading, etc.

$qlHeading = (qlNav | where { $_.Title -eq "Libraries" })[0]

If you are looking to move the heading order, then you need to get the heading you wish to move, the heading that you wish it to appear under, and then apply the Move method. For example, to move the Lists heading to appear underneath the Discussions heading, type the following:

$qlHeading = $qlNav | where { $_.Title -eq "Lists" }
$qlNewPreviousSibling = $qlNav | where { $_.Title -eq "Discussions" }
$qlHeading.Move($qlNav, $qlNewPreviousSibling)


To create a new heading, we have to use the SPNavigationNode class, which accepts the following properties:

  • Display Name (required) – Will appear in the Quick Launch as the name of the item
  • URL (required) – Hyperlink address for the item. You can set this with double-quotes if you do not want to set a URL for the item
  • External Link [$true/$false] (optional) – Specifies whether the link is internal (item in SharePoint) or external (another website). As it is set to $false by default, you only need to specify this property if creating a link to an external site.

The following example creates a heading under Libraries called “External Links”, which will appear in the Quick Launch but does not actually link to anywhere:

$qlNewPreviousSibling = $qlNav | where { $_.Title -eq "Libraries" }
$headingNode = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode("External Links", "")
$qlNav.Add($headingNode, $qlNewPreviousSibling)


To add links to a heading, we use the same SPNavigationNode class as before, with the same properties. First, we get the heading that the links will appear under and then add them to the heading as children using the Add, AddAsFirst, or AddAsLast methods. In the example below I add one internal and two external links to our new External Links heading:

$qlHeading = $qlNav | where { $_.Title -eq "External Links" }
$linkNode = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode("Get-SPScripts", "", $true)
$linkNode = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode("Links", "/sites/foundation/Lists/Links/AllItems.aspx")
$linkNode = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode("Follow me on Twitter", "", $true)

To view a list of these links after creation, type the following command:

$qlHeading.Children | select Title, ID


Finally, to move the link order, you need to get the link you wish to move, the link that you wish it to appear under, and then apply the Move method. The link can be assigned to a variable by accessing the Children property of the heading. For example, to move the “Follow me on Twitter” link to appear underneath the “Get-SPScripts” link, type the following:

$qlNewPreviousSibling = $qlHeading.Children | where { $_.Title -eq "Get-SPScripts" }
$qlLink = $qlHeading.Children | where { $_.Title -eq "Follow me on Twitter" }
$qlLink.Move($qlHeading.Children, $qlNewPreviousSibling)


The end result of all this scripting is that we now have a new heading and three links underneath that heading:


Exporting/Importing Quick Launch Navigation Items

As promised, the following scripts will provide the ability for you to export the Quick Launch navigation items from one site and import them into another site. The export script actually creates an XML file on the computer with the items listed hierarchically. The advantage with this approach is that you could create the XML file manually for import into sites as a new structure.

Here is the export script:

#Get Web and Quick Launch objects
$web = Get-SPWeb http://portal/sites/foundation
$qlNav = $web.Navigation.QuickLaunch

#Create Export File
$xmlFilePath = "C:\Install\QuickLaunchNav.xml"
New-Item $xmlFilePath -type file -force

#Export Quick Launch Navigation to XML file
Add-Content $xmlFilePath "<?xml version=`"1.0`" encoding=`"utf-8`"?>"
Add-Content $xmlFilePath "`n<Navigation>"
$webUrlXml = "`n<WebUrl>" + $web.ServerRelativeUrl + "</WebUrl>"
Add-Content $xmlFilePath $WebUrlXml
Add-Content $xmlFilePath "`n<Headings>"
$qlNav | ForEach-Object {
    $headingXML = "`n<Heading Title=`"" + $_.Title.Replace("&","&amp;") + "`" Url=`"" + $_.Url.Replace("&","&amp;") + "`">"
    Add-Content $xmlFilePath $headingXML
    $_.Children | ForEach-Object {
        $navLinkXML = "<NavLink Title=`"" + $_.Title.Replace("&","&amp;") + "`" Url=`"" + $_.Url.Replace("&","&amp;") + "`"/>"
        Add-Content $xmlFilePath $navLinkXML
    Add-Content $xmlFilePath "`n</Heading>"
Add-Content $xmlFilePath "`n</Headings>"
Add-Content $xmlFilePath "`n</Navigation>"

This script will look at the site specified and create an XML file similar to the one shown below:


One thing to note here is that we store the URL of the originating site in a <WebUrl> property. We need this when importing navigation items into other sites as we will replace the site path stored in the XML file with the site path of the destination site for any internal links – for example, if the destination site path is /sites/newsite, in the example above we will replace /sites/foundation with /sites/newsite for all internal links.

Now the import script:

#Get Web and Quick Launch objects
$web = Get-SPWeb
$qlNav = $web.Navigation.QuickLaunch

#Get XML File
$xmlFilePath = "C:\Install\QuickLaunchNav.xml"
$xmlFile = [xml](Get-Content($xmlFilePath))
$oldWebUrl = $xmlFile.Navigation.WebUrl
$currentLinks = @()

#Clear Quick Launch links
$qlNav | ForEach-Object {
    $currentLinks = $currentLinks + $_.Id
$currentLinks | ForEach-Object {
    $currentNode = $web.Navigation.GetNodeById($_)
    write-host "Deleting" $currentNode.Title "and all child navigation links..."

#Create Quick Launch Links
$xmlFile.Navigation.Headings.Heading | ForEach-Object {
    $headingNode = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode($_.Title, $_.Url.Replace($oldWebUrl, $web.ServerRelativeUrl))
    write-host "Creating Heading:" $_.Title
    $heading = $qlNav.AddAsLast($headingNode)
    $_.NavLink | ForEach-Object {
        $linkNode = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode($_.Title, $_.Url.Replace($oldWebUrl, $web.ServerRelativeUrl))
        write-host "Creating Navigation Link:" $_.Title
        $link = $heading.Children.AddAsLast($linkNode)

This script connects to the destination site, reads the XML file, clears the navigation items on the site currently, and creates the Quick Launch navigation items and links as defined in the XML file. Note that the script will wipe any navigation items on the destination site before creating these items – it will not add new items to those already present (although you could alter the script to do so). Therefore, make sure that you test, test and test again before trying this out on a live environment.


  1. Excellent stuff, just what I was looking for. I had to extend it somewhat to support things like external links and importing into a root site, but you did all the hard work!

    One funny thing I noted: $web.Navigation.QuickLaunch returned null when I had NOT installed the publishing feature. After installing the feature on the site collection, it all worked beautifully. I thought the opposite would be the case...

  2. Hi Svetho,

    Not sure why you had to extend it to support external links as the examples I used here have included them. Would be interested to know (perhaps you could share your revised version?).

    Interesting that you got null without the publishing feature activated. I had two site collections running - one with the feature activated and one without. This script was written on the one without and I have a script coming soon on the one I did with it activated (where I did have to also specify external links).

    I'll test it again. Thanks for the comments.

  3. Hi Phil,
    thank you for the feedback.

    Here are links to the updated scripts:

    Looking forward to your next posting! :-)

  4. Thanks for sharing Svetho - nice changes, btw.

    I will go back and re-test the publishing infrastructure feature activated/deactivated scenarios to make sure I'm not going mad!

  5. Svetho - For info, I did try again with two new site collections and got the same results. The script in this article worked on the site collection without the Publishing Infrastructure feature enabled but didn't on the site collection with the feature enabled - I have a script lined up for a new article on this scenario coming soon...

  6. Hi i have the following script.

    $web = Get-SPWeb http://intranet/sites/hr
    $qlNav = $web.Navigation.QuickLaunch
    $qlHeading = $qlNav | where { $_.Title -eq "Reports" }
    $linkNode = New-Object Microsoft.SharePoint.Navigation.SPNavigationNode("Report", "SitePages/Rapport_02.aspx", $true)

    I want to add this item to a collection of sites can you help me out with this i have a list with all sites that must have this navigation item

  7. Hi,

    thanks for the post!
    I have a question for you..
    Is it possible to set a relative path for $xmlFilePath instead of absolute path?
    Thanks again!

  8. THis is good stuff, Question: How do I set the Global Navigation's display the same navigation items as the parent site settings.

  9. Hi,

    nice post! Based on this I tried to update quicklaunch item title correctly in Powershell but GUI does not reflect the change and I don't know what is going wrong.

    $url = "http://webapp/sitecollection/website"
    $web = Get-SPWeb $url
    $qlNav = $web.Navigation.QuickLaunch
    $qlHeading = $qlNav | where { $_.Title -eq "OldTitle" }
    $qlHeading.Title = "NewTitle"
    & "C:\Program Files\Internet Explorer\iexplore.exe" $url

    Now IE show the OldTitle but querying it in Powershell shows NewTitle.

    If I call also $qlNav.Update() then I get
    Method invocation failed because [Microsoft.SharePoint.Navigation.SPNavigationNodeCollection] doesn't contain a method named 'Update'.
    although the method is there...
    SPNavigationNode.Update Method (Microsoft.SharePoint.Navigation)

    Do you know why are these problems happening?

  10. Hi, nice job. I had two site collections running - one with the feature activated and one without. thanks for sharing.
    Forex Software

  11. Thank You for sharing.

    Was looking for a nice way to setup some menu items using PowerShell

  12. Phil,
    I just noticed something odd - after using PowerShell to edit the current navigation on my site, the site highlighting is no longer accurate. It now highlights the parent site instead. If you use the UI to go into the navigation edit screen, simply click ok to save and exit, then everything highlights again normally.

    Any thoughts on why this may be happening or how to fix it?


  13. Brian - not sure. Could you post the navigation inheritance settings and whether this is a SharePoint Foundation or Server site?

  14. Thank you a lot for this !

    But one question remains ... I know how to create a document library, and how to create a title ...

    But how the hell ! can i create a document library, under a specific title ?

    Save me :)


  15. Hi Phil,

    one problem I can't resolve. I try to add a Link with Parameters like
    But the link will be cut before the ? and the result is just
    I also tried to escape the ? with ` but it did not work.

    1. Hi gain,

      I got it, you have to use the property for a Link (just heading don't work)
      $linkNode.Properties["NodeType"] = "AuthoredLinkPlain"

  16. This comment has been removed by the author.

  17. I have an issue with the import part of the process... If I create an XML with only Headers, and no link, the script still creates (invisible) links. How can I stop this?

  18. This blog is so nice to me. I will continue to come here again and again. Visit my link as well. Good luck
    obat aborsi
    cara menggugurkan kandungan
    obat telat datang bulan
    obat penggugur kandungan

  19. The Nike LeBron Soldier 10 Christ the King is a brand new Nike LeBron Soldier 10 that pays homage to the top NYC basketball KD 6 school, Christ the King high school.LeBron James has supported the high school for years now. Dressed in a Team Red, LeBron 14 Metallic Gold and Off-White color scheme. This release is perfect for those that either support the school or are just Basketball Shoes die-hard Cleveland Cavaliers fans. Featuring a Team Red-based upper with Metallic Gold accents throughout that sits atop an Off-White rubbers Kobe 11 sole.Look for the Nike LeBron Soldier 10 “Christ the King” to release on Saturday, October 15th at select Nike Basketball Curry 3 USA retail stores. The retail price tag is set at $130 USD.
    The Oregon Ducks basketball squad will be rocking a Kobe venomenon 5 special edition Nike KD 9 PE for Veteran’s Day.This Oregon Ducks Nike KD 9 PE comes dressed in a Black, NBA Store Green and Yellow color scheme that includes feather print detailing and sitting atop a clear translucent outsole.To go along with Cavalier Steam Shop their exclusive Nike KD 9, the team will also be rocking their special edition digital camo “Fighting Ducks” uniform.Check out Warriors Team Store the uniforms and KD 9s below and look for the Oregon Ducks in the Veteran’s Day getup this Friday against KD shoes Army.
    Jordan Brand will be releasing an Air Jordan 9 Retro that pays homage to Kobe Bryant — although, we’re NBA Stars Shoes not sure if that is the official story they’ll be running with.These are scheduled to release on November 19 for Kobe 8 $190, and are nearly identical to the pair that was made for Kobe Bryant while he and Shaq were teammates. kobe 10 elite They actually had matching pairs, only difference being they each had their jersey numbers listed on the heel of the Kobe shoes shoe. Kobe wore 8 back then, for those that don’t remember.When we mention that they’re nearly identical it’s because they KD 7 went ahead and changed the 8 to a 23. The right outsole also has the backwards Jumpman — not exactly Kobe 9 remastered either.Check out the official images below and let us know if you plan on grabbing a pair.

  20. thanks for article ... that was awesome....really useful
    best regard
    song2song giftstar divecenter

  21. [url=][b]adidas yeezy boost 350[/b][/url]
    [url=][b]coach outlet online[/b][/url]
    [url=][b]moncler jackets[/b][/url]
    [url=][b]stan smith adidas[/b][/url]
    [url=][b]adidas uk[/b][/url]
    [url=][b]toms outlet[/b][/url]
    [url=][b]pandora charms sale clearance[/b][/url]
    [url=][b]michael kors outlet clearance[/b][/url]
    [url=][b]coach outlet store online[/b][/url]

  22. I found so many interesting stuff in your blog especially its discussion. From the tons of comments on your articles, I guess I am not the only one having all the enjoyment here! keep up the good work
    tips memilih jasa penyewaan truk terpercaya di indonesia
    tips memilih truk
    jasa penyewaan truk
    penyewaan truk terpercaya
    penyewaan truk indonesia
    memilih jasa penyewaan truk

  23. Greetings admin
    I like your topic, after reading your article very helpful at all and can be a source of reference
    I will wait for your next article updates
    Thank you, for sharing


    penirum asli

    Titan Gel


    Hammer Of Thor

  24. This comment has been removed by the author.

  25. Which little will involve true persuits projects, Levy, Brokerage firm as well fines. This unique total number is controlled by change and soon you make payments. The local surf forecast in an european affiliate state's borders except for usa, Transfer cask off this invest certainly not recoverable.

    Here numerous is made up of applied persuits chores, Duty, Stock broker too service expenses. Them figure is susceptible to change if resultados de futbol you camisetas de futbol baratas do not make agreed paying. The local surf forecast in an western european user level Maillot De Foot Pas Cher in addition british, dfb trikot müller Transfer cask off this sale made not really recoverable.

    Regarding money also should include topical persuits works, Place a burden on, Broker properly fines. This skill presence is Maglie Da Calcio a Poco Prezzo cause to undergo change unless you make settlement. The local surf forecast in an western european person proclaim better british isles, Transfer value-added tax to this receive not really recoverable.

    Furla is an extra chinese make typically specialises present when of add-ons, Possessions as well footwear types. The kind was likely conceptualized Maglie Poco Prezzo located inside of 1927 because of Furlanetto in addition to nonetheless ran herm instantly. Furla ipad fixtures equipement foot was initially achieved of Arlo amazon müller trikot Furlanetto within maillot de foot personnalise just Bologna, Toscana of 1927 to get automatic merchandiser about stylish Camisetas De Futbol Baratas solutions pertaining to.

  26. Greetings admin
    I like your topic, after reading your article very helpful at all and can be a source of reference
    I will wait for your next article updates
    Thank you, for sharing

    Obat Aborsi

    Jual Obat Aborsi

    Obat Penggugur Kandungan

    Obat Abosi 1 Bulan

    Obat Abosi 2 Bulan

    Obat Abosi 3 Bulan

    Obat Abosi 4 Bulan

    Obat Abosi 5 Bulan

    Obat Abosi 6 Bulan

  27. Hey Thanks for sharing this valuable information with us. I will come back to your site and keep sharing this information with us.
    Best Regards -

  28. Are you blacklisted? Struggling to get a personal loan? Has your application been DECLINED due to Low Credit Score? Over COMMITTED? Affordability? But you know you can afford this loan. Loans Approved in 4hours, you can email us at

    Loan Amount Needed:
    Loan Duration:
    Your Country:
    Mobile NO:
    Purpose Of Loan:
    Email Address:
    monthly income:

    Opportunity Financial, LLC

  29. What a way to express things. I have found comfort in reading this post and i am sure other users may feel the same, because this post carries a social message in it. Keep it up ! Regards:- | |

  30. Investigate to the Sign in screen in the YouTube application and stay on this screen until you've completed the remainder of the systems. Visit on your PC or phone. Sign in when affected. Incitation code and sign in Navigate to the Sign in screen in the YouTube application and stay on this screen until you've completed the remainder of the techniques. Visit on your PC or phone. Sign in when affected: Read more...