Thursday, 21 April 2011

Managing Quick Launch (Current) navigation for SharePoint Publishing sites using PowerShell

A few weeks back I published an article on using PowerShell to manage the Quick Launch (otherwise known as “Current”) navigation on SharePoint Foundation sites – or sites in SharePoint Server 2010 where the “SharePoint Server Publishing Infrastructure” site collection feature is not activated.

In this article I will go through a similar scenario of managing headings and links in Quick Launch navigation, but this time where you are using SharePoint Server with the Publishing Infrastructure feature enabled on the site collection. There is also an extra scenario to mention here as well, where the sites within the site collection are actual publishing sites – i.e., sites with the “SharePoint Server Publishing” site feature activated.

First, to clarify, the “SharePoint Server Publishing Infrastructure” feature can be activated on the site collection from the Site collection features option in the Site Settings administration page on the root site of the site collection:


I’m not going to go into the exact specifics of what this feature does, but from a navigation point of view, it provides extra options for inheriting links from parent sites, automatic sorting, and additional options for headings and links, including setting a separate title and description, opening in a new window, and applying audience filtering.

Because of these additional options, the code for managing headings and links in PowerShell is also different. First, we need to get the Web, PublishingWeb 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/nav:

$web = Get-SPWeb http://portal/sites/nav
$pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
$qlNav = $pubWeb.Navigation.CurrentNavigationNodes

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)


So far, this script has been almost the same as the script for managing Quick Launch navigation in SharePoint Foundation sites – however, here is where it is all about to change. Before I start creating new navigation items, I will assign the CreateSPNavigationNode method to a variable to make it easier to invoke later on in the script:

$CreateSPNavigationNode = [Microsoft.SharePoint.Publishing.Navigation.SPNavigationSiteMapNode]::CreateSPNavigationNode

To create a new heading or link, you have to specify the following information:

  • Display Name – Will appear in the Quick Launch as the name of the item
  • URL – Hyperlink address for the item. You can set this with double-quotes if you do not want to set a URL for the item
  • Node Type – This will specify the type of node available in SharePoint 2010 – e.g., Heading for a navigation heading and AuthoredLinkPlain for a generic link. You can get a full list of available node types from this article:
  • SPNavigationNodeCollection to add the new node into

For example, the following lines of script will add a new heading called “External Links” under the existing “Libraries” heading:

$qlNewPreviousSibling = $qlNav | where { $_.Title -eq "Libraries" }
$headingNode = $CreateSPNavigationNode.Invoke("External Links", "", [Microsoft.SharePoint.Publishing.NodeTypes]::Heading, $qlNav)
$headingNode.Move($qlNav, $qlNewPreviousSibling)


To add links to a heading, we use the same CreateSPNavigationNode method 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. 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" }).Children
$linkNode = $CreateSPNavigationNode.Invoke("Get-SPScripts", "", [Microsoft.SharePoint.Publishing.NodeTypes]::AuthoredLinkPlain, $qlHeading)
$linkNode = $CreateSPNavigationNode.Invoke("Links", "/sites/nav/Lists/Links/AllItems.aspx", [Microsoft.SharePoint.Publishing.NodeTypes]::AuthoredLinkPlain, $qlHeading)
$linkNode = $CreateSPNavigationNode.Invoke("Follow me on Twitter", "", [Microsoft.SharePoint.Publishing.NodeTypes]::AuthoredLinkPlain, $qlHeading)

Because the $linkNode variable is being assigned as each link is created, you can use this opportunity to set additional properties, such as a Description, Target (i.e., Open link in new window), and Audience. Adding the section of script below directly after the “Follow me on Twitter” link has been created will set the options shown in the following screenshot:

$linkNode.Properties["Description"] = "Test description created with PowerShell"
$linkNode.Properties["Target"] = "_blank"
$linkNode.Properties["Audience"] = "All site users"


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

$qlHeading | 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:

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


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


Configuring Quick Launch Options

As mentioned at the start of this article, activating the “SharePoint Server Publishing Infrastructure” site collection feature provides extra options for inheriting links from parent sites and automatic link sorting. To configure these in PowerShell, start by getting the Web and PublishingWeb objects and assigning them to variables. To show the inheritance options available, this example calls a sub-site to the root of the http://portal/sites/nav site used earlier:

$web = Get-SPWeb http://portal/sites/nav/subsite
$pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)

The following table shows the options available in the UI followed by the corresponding script to modify them using PowerShell:

image Display the same navigation items as the parent site:

$pubWeb.Navigation.InheritCurrent = $true
$pubWeb.Navigation.ShowSiblings = $false

Display the current site, the navigation items below the current site, and the current site’s siblings:

$pubWeb.Navigation.InheritCurrent = $false
$pubWeb.Navigation.ShowSiblings = $true

Display only the navigation items below the current site (shown left):

$pubWeb.Navigation.InheritCurrent = $false
$pubWeb.Navigation.ShowSiblings = $false

image Show subsites:

$pubWeb.Navigation.CurrentIncludeSubSites = $true


Show pages (publishing sites only):

$pubWeb.Navigation.CurrentIncludePages = $true

image Maximum number of 30 dynamic items to show within this level of navigation:

$pubWeb.Navigation.CurrentDynamicChildLimit = 30

image Sort manually:

$pubWeb.Navigation.OrderingMethod = "Manual"

image Sort automatically:

$pubWeb.Navigation.OrderingMethod = "Automatic"

Sort by Title (shown left):

$pubWeb.Navigation.AutomaticSortingMethod = "Title"

Sort by Created Date:

$pubWeb.Navigation.AutomaticSortingMethod = "CreatedDate"

Sort by Last Modified Date:

$pubWeb.Navigation.AutomaticSortingMethod = "LastModifiedDate"

Sort in ascending order (shown left):

$pubWeb.Navigation.SortAscending = $true

Sort in descending order:

$pubWeb.Navigation.SortAscending = $false

image Sort manually with automatic page sorting (publishing sites only):

$pubWeb.Navigation.OrderingMethod = "ManualWithAutomaticPageSorting”

Once you have chosen the options for the script, add the following lines at the end to apply the changes and dispose of the SPWeb object:


Friday, 1 April 2011

Mask created/modified user name from SharePoint list item forms and views using PowerShell

Short and sweet this one. As you probably know, whenever you view a list item in SharePoint, the display form shows the date and time that the item was created and last modified along with the name of the user that performed those operations. An example is shown in the screenshot below:


There may be occasions where the user name should be hidden from view for security or other purposes. This feature is normally used by SharePoint for the “Show user names in survey results” option on surveys, but it can be applied to any other list or document library by setting the ShowUser property of a list to false using the small PowerShell script below:

#Get Web and List objects
$web = Get-SPWeb http://SiteUrl
$list = $web.Lists["List Name"]

#Disable user from appearing in item dialogs
$list.ShowUser = $false

#Dispose of Web object

Once this script has been run on a list, the item display form looks like this:


Note that this also affects the Modified By and Created By columns in list views:


To restore the user name on the list form again, simply set the ShowUser property back to true.