Archives / 2012 / March
  • PowerShell script to find where in a site collection a specific feature is enabled.

    Tags: PowerShell, SharePoint

    It's not an uncommon task to want to find out in what webs you have a specific feature enabled.  This little script does just that, taking 2 params (site collection url, feature name) and simple output the SharePoint web url.  Nothing fancy, but certainly a useful script to have in your toolbox!

    A good example of this is where you are using content publishing going from an Enterprise internal farm to a Foundation external farm, certain feature won’t be in the Foundation farm and will cause the Content Publisher to fail, it will be so kind as to tell you what feature is causing the problem, but not where it is!  Someone somewhere has enabled a feature they shouldn’t have!!!

    I’m sure some “one line wizards” could optimise this script – but that’s not my bag – I’m interested in getting the job done for our clients and providing a useful script we can use again and again.

    You could of course add in Disable-SPFeature command if you wanted to do that at the same time…

    #Powershell script to identify where in a site collection a specific feature is enabled
    #Version: 1.0
    #Author: Steve Clements | Perspicuity Ltd
    #$siteCollectionUrl - url of the site collection
    #$featureName - name of the feature you want to find
    param ([string] $siteCollectionUrl, [string] $featureName)
    if(!$siteCollectionUrl-or!$featureName) {
        Write-Host-ForegroundColorRed"You must provide a site collection url and feature name to find!"
    Write-Host-BackgroundColorDarkGreen"Feature '"$featureName"' exists in these sites"
    Get-SPSite$siteCollectionUrl | ForEach-Object {
        Get-SPWeb-Site$_ | ForEach-Object {
          $f=Get-SPFeature-Web$_ | Where {$_.DisplayName -eq$featureName}
      if($f) {


  • Gotcha: 403 and 401 errors in SharePoint using Anonymous access

    Tags: SharePoint

    Recently I came up against a problem where I was getting 401 Unauthorized and 403 Forbidden errors in SharePoint on an extended anonymous only site.

    It worked perfectly when using windows authentication, for any level of user.

    In the end I tracked the problem down to accessing SPContext.Current

    I found this article which states you should use SPSecurity.RunWithElevatedPrivileges when using the current context and it worked!!

    A little surprising, but not unexpected the SharePoint logs showed nothing about this problem.

    Check out the link above which gives a perfect little code snippet of how to resolve the problem.


  • Enable Publishing Approval workflow on all SP Web(s) in an Site collection with Powershell

    Tags: PowerShell, SharePoint

    What you need / What you've got?

    1. Pretty obvious, when a user edits/changes a page, you need someone to check its all good before it goes live! Aka Publishing Approval
    2. You can use the "Publishing site with workflow" template or enable it manually or set it up in your custom site definition.
    3.'ve got an entire site collection full of web sites and you need to do it "en-mass" … step up Powershell.
      1. A common scenario could be you were working in Stage or Pre-go live and having Approval workflow just isn't practical or required. Now its need and want it.

    What you need to do to SharePoint...

    1. Enable Moderation on the library (that is Content Approval in UI)
    2. Enable Minor Versions (that’s is 1.1, 1.2 etc)
    3. Create the Workflow History list and enable the Workflow History feature (hiding this list is optional, but I think its best, showing the list offers nothing to the user, you can access the same history looking at the workflow status screen, which is far more usefully presented)
    4. Create the Workflow Tasks list
    5. Associate the "Publishing Approval" workflow to the library
    6. Set the properties on the WorkFlow association
      1. This is your choice, but I have set AllowManual to true, AutoStartCreate and Change to false
    7. Add the association
    8. You would be forgiven in thinking that’s it, job done...but you will find that the even though the workflow is there, it doesn't the "major check-in" property enabled so the experience for the user is different i.e they have to choose the non-default option to fire the workflow.
    9. You need to set the property DefaultContentApprovalWorkflowId to the id of the Workflow association object, what tricked me up...even though in the UI the property is in the workflow with the other workflow properties, but this property is on the library.
    10. Still not, the workflow is firing great, but every status is "Rejected". Why? Because you need to Update the workflow association data.
    11. For this I cheated and setup 1 workflow on the pages library, with the correct actions and Approvers group, then went into SharePoint Manager and grabbed the xml from there.
    12. Also I set the Enabled property to true and call WorkflowAssociations.Update(myAssociation) to set both new properties…
    13. Yes, that’s are actually done now!!!

    The Magic

    This script is 99% influenced by this post, I’ve butchered it and added the extra stuff required… FYI: is a great resource for SharePoint PowerShell scripts...the scripts published are always of high quality, well commented and explained - bookmark it if you don't like thrashing.

    The crazy colours and rather OTT output is my fault!

    I’ve also put the params at the top – not overly user friendly, but this is perfect for my requirements…you can easily change that!

    $url="<site collection URL>"
    $workFlowName="Publishing Approval"
    $wfassname="Page Approval"
    functionAddWorkflowToLibraries ($SiteCollection, $ListName, $WfName, $WfAssociationName)
       #Get site object and create blank guid to store workflow template ID
        # Get every sub web
        Get-SPWeb-Site$site | ForEach-Object {
      Write-Host-ForegroundColorWhite-BackgroundColorDarkMagenta"WEB: "$_.Title$_.Url
            #Do the following if a list exists with the name specified by the user - e.g., Pages
            if ($_.Lists[$ListName]) {
                # Get list and set version properties
                $list.EnableModeration =$true
                $list.EnableMinorVersions =$true
               #Go through each workflow installed in the site to find the correct ID            
                foreach ($wfTemplatein$_.WorkflowTemplates) {
                    if ($wfTemplate.Name -eq$WfName) {
                if($wfTemplate-eq$null) {
                    Write-Host"ERROR: Workflow '"$WfName"' with ID '"$wfTemplateId"' NOT found"-BackgroundColorRed-ForegroundColorWhite
                else {
                    #Check if the site already has a workflow history list - if not, create it
                if(!$_.Lists["Workflow History"])
                        Write-Host"CREATE: Workflow History list"-ForegroundColorBlue
                    $_.Lists.Add("Workflow History", "A system library used to store workflow history information that is created in this site.  It is created by the Publishing feature.",
                        "WorkflowHistory", "00BFEA71-4EA5-48D4-A4AD-305CF7030140", 140, "100")
                        if (!$_.Features["00BFEA71-4EA5-48D4-A4AD-305CF7030140"]) {
                        $wfHistory=$_.Lists["Workflow History"]
                        $wfHistory.Hidden =$true
                        Write-Host"FOUND: Workflow History list"-ForegroundColorgreen
                    $wfHistory=$_.Lists["Workflow History"]
                    #Check if the site already has a workflow tasks list - if not, create it
                if(!$_.Lists["Workflow Tasks"]) {
                        $_.Lists.Add("Workflow Tasks", "This system library was created by the Publishing feature to store workflow tasks that are created in this site.", "WorkflowTasks", "BF611337-1591-49f4-BF42-CE7BE53852D8", 107, "100")
                        Write-Host"CREATE: Workflow Tasks list"-ForegroundColorBlue
                    else {
                        Write-Host"FOUND: Workflow Tasks list"-ForegroundColorgreen
                $wfTasks=$_.Lists["Workflow Tasks"]
                    #new up workflow association (extra associated data can be added if you have it)
                $wfAssociation= [Microsoft.SharePoint.Workflow.SPWorkflowAssociation]::CreateListAssociation($wfTemplate, $WfAssociationName, $wfTasks, $wfhistory)
                    $wfAssociation.AllowManual =$true
                    #$wfAssociation.AllowAsyncManualStart = $true
                    $wfAssociation.AutoStartChange =$false
                    $wfAssociation.AutoStartCreate =$false
                    #Check to see if the association has already been added to the list
                    foreach ($wfin$list.WorkflowAssociations) {
                        if ($wf.Name -eq$wfAssociation.Name) {
                            write-host"FOUND: Workflow"$wf.Name"already exists on"$list.Title"list in site"$_.Title-ForegroundColorgreen
                    #If association is already there, ignore the add (and optionally delete it)
                if ($wfFound-eq$true) {
                        #Command to remove existing workflow from list before adding new one, if required
                    write-host"REMOVE: Workflow"$wfAssociation.Name"from"$list.Title"in site"$_.Title-ForegroundColorMagenta
                    #else, add it to the workflow association to the list
                        #Create the association
                    $list.WorkflowAssociations.Add($wfAssociation) | Out-Null
                        #Set the association data (for approvers and approval steps
                        $wfAssociation.AssociationData =Get-AssociationData
                        #enable is not available until its associated.
                        $wfAssociation.Enabled =$true
                        $list.DefaultContentApprovalWorkflowId =$wfAssociation.Id
                        write-host"CREATE: Workflow"$wfAssociation.Name"to"$list.Title"in site"$_.Title-BackgroundColorCyan-ForegroundColorRed
            else {
                Write-Host-BackgroundColorDarkRed-ForegroundColorWhite"No"$listName" list found"
       #Dispose of Site object
    functionGet-AssociationData() {
        return"<dfs:myFields xmlns:xsd=`"`" xmlns:dms=`"`" xmlns:dfs=`"`" xmlns:q=`"`" xmlns:d=`"`" xmlns:ma=`"`" xmlns:pc=`"`" xmlns:xsi=`"`"><dfs:queryFields /><dfs:dataFields><d:SharePointListItem_RW><d:Approvers><d:Assignment><d:Assignee><pc:Person><pc:DisplayName>Approvers</pc:DisplayName><pc:AccountId>Approvers</pc:AccountId><pc:AccountType>SharePointGroup</pc:AccountType></pc:Person></d:Assignee><d:Stage xsi:nil=`"true`" /><d:AssignmentType>Serial</d:AssignmentType></d:Assignment></d:Approvers><d:ExpandGroups>false</d:ExpandGroups><d:NotificationMessage /><d:DueDateforAllTasks xsi:nil=`"true`" /><d:DurationforSerialTasks xsi:nil=`"true`" /><d:DurationUnits>Day</d:DurationUnits><d:CC /><d:CancelonRejection>true</d:CancelonRejection><d:CancelonChange>true</d:CancelonChange><d:EnableContentApproval>true</d:EnableContentApproval></d:SharePointListItem_RW></dfs:dataFields></dfs:myFields>"


  • SharePoint 2010 set "Start this workflow to approve publishing a major version of an item" with Powershell

    Tags: SharePoint

    Took me a little while to figure this one out, you’ve assigned your workflow to a library and you can set all other other flags like “AllowStartChange” and “AllowStartCreate”, but cant see how to set “Start this workflow to approve publishing a major version of an item.”

    That’s because its a property on the library itself called “DefaultContentApprovalWorkflowId”

    So you might want to do something like this…where you have the WorkFlow Association object ($wfAssociation) and the list/library ($list).

    $wfAssociation = [Microsoft.SharePoint.Workflow.SPWorkflowAssociation]::CreateListAssociation(……
    $list.WorkflowAssociations.Add($wfAssociation) | Out-Null
    $list.DefaultContentApprovalWorkflowId = $wfAssociation.Id


    This is probably the best Associate workflow to list/library with Powershell example out there