Run all SharePoint Health Analyzer Jobs with PowerShell

Today I had a need to run all health analyzer jobs to make sure everything was good after a clean install of SharePoint 2010. Of course I knew there had to be a quick PowerShell approach to this. I did a quick search and found a few different variations of the same basic code, so I took what I liked and made it into a simple function that I will store in the profile on my SP machines going forward.

The blog that had exactly what I wanted, both in the body and the comments was Matthew McDermott’s blog – here. Matthew has a more structured approach using a foreach loop to iterate through each job in the collection, and then he calls the RunNow() method to start the jobs. Gary LaPointe commented and provided a one-liner, which I’m going to use – although I am putting that one-liner into a function…

By making a simple function, I can just run the function like a cmdlet – so it makes it very easy to run going forward.

Here is the function:

function Start-SPHealthTimerJobs {Get-SPTimerJob | Where-Object {$_.Title -like “*Health Analysis Job*”} | Start-SPTimerJob}

And to run it, I simply type:


Configure Web.Config Custom Errors using PowerShell

It seems like every time I go to disable custom errors for the purposes of troubleshooting, I have to turn to the interwebs to remember the exact settings I need to change and what I need to change them to. Of course it’s all done in the web.config file for the web application with which you are working – and it’s really just two settings that need tweaked…

Instead of doing this manually, I thought “What if I could create two PowerShell Functions to manipulate these values?”

Well, lucky for me I had already done this to enable and disable SP Blob Caching – so it was pretty easy to modify that code to change the customErrors and CallStack settings in the web.config.

Essentially the hardest part is making sure you grab the right configuration path from the web.config, once you’ve got that, it’s just a matter of creating a new object (Microsoft.SharePoint.Administration.SPWebConfigModification) and then setting values of that object.

Once you’ve created your 2 $configMod objects, you call the $webapp.WebConfigModifications.Add method for each mod – and then call the Update() method to apply. Hit your page again and you should see an uglier, yet more informational error message.

Once you have dot-sourced the function, here is how you disable the SharePoint (custom) Errors:

Disable-SPCustomErrors -WebApplication http://webappurl

And here is how you re-enable the SharePoint (custom) Errors:

Enable-SPCustomErrors -WebApplication http://webappurl

And without further ado, here is the code containing two functions – Enable-SPCustomErrors and Disable-SPCustomErrors:

# Disable-SPCustomErrors Function
function Disable-SPCustomErrors { 
	[Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)]

process { 
    $WebApp = $WebApplication.Read() 
    # SPWebConfigModification to enable/disable CustomErrors
    $configMod1 = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification 
    $configMod1.Path = "configuration/system.web/customErrors" 
    $configMod1.Name = "mode" 
    $configMod1.Sequence = 0 
    $configMod1.Owner = "CustomErrorsMod" 
    ## SPWebConfigModificationType.EnsureChildNode -> 0 
    ## SPWebConfigModificationType.EnsureAttribute -> 1 
    ## SPWebConfigModificationType.EnsureSection -> 2 
    $configMod1.Type = 1 
    $configMod1.Value = "Off"
	# SPWebConfigModification to enable/disable CustomErrors 
    $configMod2 = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification 
    $configMod2.Path = "configuration/SharePoint/SafeMode" 
    $configMod2.Name = "CallStack" 
    $configMod2.Sequence = 0 
    $configMod2.Owner = "CustomErrorsMod" 
    ## SPWebConfigModificationType.EnsureChildNode -> 0 
    ## SPWebConfigModificationType.EnsureAttribute -> 1 
    ## SPWebConfigModificationType.EnsureSection -> 2 
    $configMod2.Type = 1 
    $configMod2.Value = "true" 
    # Add mods, update, and apply 
    $WebApp.WebConfigModifications.Add( $configMod1 ) 
    $WebApp.WebConfigModifications.Add( $configMod2 )

# Enable-SPCustomErrors Function
function Enable-SPCustomErrors { 
    [Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)] 

process { 
    $WebApp = $WebApplication.Read() 
    $mods = @() 
    foreach ( $mod in $WebApp.WebConfigModifications ) { 
        if ( $mod.Owner -eq "CustomErrorsMod" ) { 
            $mods += $mod 
    foreach ( $mod in $mods ) { 
        [void] $WebApp.WebConfigModifications.Remove( $mod ) 

Access Denied while creating Publishing Pages

I ran into one of those weird errors that just kind of gets under your skin because you think you’ve checked everything.

You’ve all seen Access Denied errors in SharePoint, but have you run into the one where users WITH proper permissions get it when trying to create a list item – in this case Publishing Pages? Very bizarre.

I checked all of the usual suspects, permission inheritance, draft items in Style Library, Master Page Gallery, etc. Nothing. But then when I reached out to the search engines just for giggles, I found this post by Gunnar Peipman which gave me exactly what I needed.

The permissions on the Master Page Gallery are unique, and users need at least “Restricted Read” to create pages. What’s frustrating is if you go into Site Permissions and view the Uniquely Secured Content, Master Page Gallery DOES NOT show up in that list. You’d think it would show you all uniquely secured content, but that’s not the case.

Thanks Gunnar for the short post with the fix!

1.Go to Site Actions -> Site Settings ->Modify all site settings
2.Go to Galleries -> Master pages and page layouts
3.From the list toolbar, select Settings -> Document library settings
4.Select permissions for this document library
5.Add ‘Restricted Read’ access to the required groups.

Use Find/Replace in PowerShell to fix InfoPath Forms after moving to a new Site Collection

I know I know, that’s a really long title.

I found some pretty good PowerShell how-to’s which described how to use Get-ChildItem to iterate through a folder – checking each item for a string and then using -replace to fix the string.

However, my situation was slightly different as I wanted to walk through a SharePoint 2010 Form Library – fixing InfoPath forms which had been moved into a new site collection and thus did not open in the browser and would not save due to the old reference to the XSN.

I’m sure there may be better methods on moving XSNs and XMLs across site collections where maybe this wouldn’t be necessary, but if you’re reading this I’ll assume you don’t care.

In any case, what I ended up doing (after obviously re-publishing the XSN template to the new site collection so new IP forms wouold work) is:

  1. Copy all of the forms using Windows Explorer (we didn’t care about versions or modified by metadata, just the content type metadata) into the new Form Lib.
  2. Run the following PowerShell code to fix each XML file – replacing the link to the old XSN with a link to the new XSN (Note: I ran this on my desktop, NOT on the server as I didn’t need any SP cmdlets):
$files = Get-ChildItem \\sitecollection\davwwwroot\FormLib -Filter "*.xml"
foreach ($file in $files) {
(Get-Content $file.fullname) | ForEach-Object {$_ -replace "http://sitecollection/library/OLDXSNPATH.xsn", "http://newsitecollection/library/NEWXSNPATH.xsn"} | Set-Content $file.fullname

Voila, all IP forms are now fixed and will not only open in the browser as expected – but I can now update these forms in the new location as they now point to the correct XSN template.

If you’re a frequent reader you’re probably thinking “Wow, normally he gives us these nice functions with parameters, help, etc.”… You’re right, this time it was a quick and dirty chunk of code. However, chances are I’ll need to do this again – so I did actually write a function for future needs:

function Reset-InfoPathTemplateLink {
$files = Get-ChildItem $FilePath -Filter $FileExtension
	foreach ($file in $files) {
		(Get-Content $file.fullname) |
		ForEach-Object {$_ -replace $OldPath,$NewPath} |
		Set-Content $file.fullname
	} #end foreach
} #end function

To run the function, first dot-source it and then use the following syntax:

Reset-InfoPathTemplateLink -FilePath "\\sitecollection\subsite\formlib" -FileExtension "*.xml" -OldPath "http://sitecollection/doclib/template.xsn" -NewPath "http://newsitecollection/newdoclib/newtemplate.xsn"

As always, happy PowerShelling!

Generic Error on Listedit.aspx page after SP1 and Aug 2011 CU

Wow did this issue get under my skin.

At my current client, where their SharePoint 2010 Enterprise Intranet is about as business critical as a SP environment can be – I performed the SP1 and Aug 2011 CU updates. The updates themselves went about as smooth as could be expected, until we noticed that lists and libraries would give the generic error w/ correlation ID when navigating to the List Settings page (/_layouts/listedit.aspx).

This seemed like not too big of a deal on the first site collection we noticed it on – then we realized it was farm-wide.

After doing a lot of log-reading, re-running PSCONFIG.exe to ensure that everything completed from an upgrade perspective; we were in the dark…

This morning I noticed something while browsing through the layouts folder – listedit.aspx (and some other files) was modified on 6/8/2011 at 11:46 AM. Most of the other aspx files were showing a modified date much further in the past.

On a whim I copied listedit.aspx from a known-good farm into my broken farm and VOILA – lists and libraries work again.

This might not help anybody, because I couldn’t find anyone else having this exact issue – but I didn’t want to lose track of the “fix.”