Wednesday, 15 June 2011

Diagnose MissingSetupFile issues from the SharePoint Health Analyzer using PowerShell

A couple of weeks back I posted an article on how to remove missing features from a content database when you receive the [MissingFeature] error in the SharePoint Health Analyzer. I have since received quite a few requests on how to resolve the [MissingSetupFile] error, which also appears in the Health Analyzer under the “Configuration” category with the title “Missing server side dependencies”:

Missing server side dependencies

The error message reported will look similar to this one:

[MissingSetupFile] File [Features\ReviewPageListInstances\Files\Workflows\ReviewPage\ReviewPage.xoml] is referenced [1] times in the database [SharePoint_Content_Portal], but is not installed on the current farm. Please install any feature/solution which contains this file. One or more setup files are referenced in the database [SharePoint_Content_Portal], but are not installed on the current farm. Please install any feature or solution which contains these files.

Easily the best way of resolving these issues is to do as the error suggests and install the missing feature or solution, but if this is not possible or feasible to do in your scenario, there are some ways of using PowerShell to locate the source of the error in the content database and act on it accordingly.

There isn’t really a silver bullet to resolving the issue in all cases as the error could be referring to themes, files, workflows, web parts, and more. The key here is to find the file that references the missing setup file and then deal with it appropriately. Since we don’t know which site contains the file from the error message reported in the Health Analyzer, the best way I have found to diagnose the issue is to examine the content database using a SQL query in order to locate the file reporting the problem.

To help with this, I have adapted a PowerShell script from “Jelly” in this article (thanks Jelly) and created the following function:

function Run-SQLQuery ($SqlServer, $SqlDatabase, $SqlQuery)
{
    $SqlConnection = New-Object System.Data.SqlClient.SqlConnection
    $SqlConnection.ConnectionString = "Server =" + $SqlServer + "; Database =" + $SqlDatabase + "; Integrated Security = True"
    $SqlCmd = New-Object System.Data.SqlClient.SqlCommand
    $SqlCmd.CommandText = $SqlQuery
    $SqlCmd.Connection = $SqlConnection
    $SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
    $SqlAdapter.SelectCommand = $SqlCmd
    $DataSet = New-Object System.Data.DataSet
    $SqlAdapter.Fill($DataSet)
    $SqlConnection.Close()
    $DataSet.Tables[0]
}

After you have loaded the function in a PowerShell console, you can run it by using the Run-SQLQuery command with the options relevant to your deployment. For [MissingSetupFile] errors, you need to run a SQL SELECT query on the “AllDocs” table in the content database exhibiting the problem. For example, you would type the following command to examine the location of the “Features\ReviewPageListInstances\Files\Workflows\ReviewPage\ReviewPage.xoml” file reported in the [MissingSetupFile] error at the top of this article:

Run-SQLQuery -SqlServer "SQLSERVER" -SqlDatabase "SharePoint_Content_Portal" -SqlQuery "SELECT * from AllDocs where SetupPath = 'Features\ReviewPageListInstances\Files\Workflows\ReviewPage\ReviewPage.xoml'" | select Id, SiteId, DirName, LeafName, WebId, ListId | Format-List

To run this in your environment, replace “SQLSERVER” with the name of the SQL server hosting your content databases, “SharePoint_Content_Portal” with the name of the content database, and the file path in the SELECT query with the path of the missing setup file reported in the Health Analyzer (make sure this file path is enclosed in single quotes as shown above).

When the script is run, it will produce an output similar to the text below:

Id       : f5fc66e7-920a-4b44-9e3d-3a5ab825093f
SiteId   : 7b4d043c-8bbe-4068-ad91-3c270dfae151
DirName  : subsite/Workflows/Review Page
LeafName : Review Page.xoml
WebId    : 1876be06-419f-46fb-a942-a15e510f1a70
ListId   : a04dda01-a52d-4d5b-b3b4-fcd70a05e4ba

Now we have the SiteId and WebId, we can use them in a few lines of PowerShell script to display the URL of the site containing the problem file:

$site = Get-SPSite -Limit all | where { $_.Id -eq "7b4d043c-8bbe-4068-ad91-3c270dfae151" }
$web = $site | Get-SPWeb -Limit all | where { $_.Id -eq "1876be06-419f-46fb-a942-a15e510f1a70" }
$web.Url

In case it isn’t clear from the “DirName” value reported from the SQL query output, you can also use PowerShell to get the URL of the actual file causing the issue by calling the “Id” field of the item:

$file = $web.GetFile([Guid]”f5fc66e7-920a-4b44-9e3d-3a5ab825093f”)
$file.ServerRelativeUrl

Now you have to decide what to do with the offending file. In the case of the error I reported at the top of this article, the file came from a workflow deployed to the site using a feature, which was not deactivated from the site prior to removing the solution from the farm. Therefore, to solve the issue I just used SharePoint Designer to remove the workflow from the site. In the case of web parts, removing web parts from the page reported in the Health Analyzer may solve the issue. Once you have dealt with the problem file, you should now be able to reanalyse the “Missing server side dependencies” issue in the Health Analyzer to clear the problem.

Please note that if you do decide to delete a workflow or a file from the site, remember to remove the file from the site Recycle Bin and Site Collection Recycle Bin to ensure the file is removed from the content database. If not, the error may not disappear from the Health Analyzer.

If you found this article looking for information on how to diagnose MissingFeature issues in the SharePoint Health Analyzer, rather than the MissingSetupFile issue, then have a look at this article for help. For information on troubleshooting MissingWebPart and MissingAssembly errors, take a look at this article.

Monday, 6 June 2011

SharePoint 2010 & PowerShell Fundamentals presentation from SUGUK

Linked below is a copy of the presentation I delivered at the West Midlands SharePoint User Group UK meeting on 25th May. I decided to cover the fundamentals of PowerShell and how to use it to manage SharePoint 2010.

http://suguk.org/files/7/slides/entry26760.aspx

I had requested a half hour slot to deliver this, but in hindsight, probably should have gone for more as it would have allowed me to show more demos rather than present a whole load of slides. At some point in the future I hope to run a session covering PowerShell and SharePoint 2010 in more depth, where I shall focus more on the scripts themselves.

There were also great presentations on the day from Charlie Lee (Introduction to Custom Claims Providers) and Ant Clay (Taking the Geek out of SharePoint project Governance) – I don’t think anyone in the room couldn’t say they learnt at least something from the event.

If you decide to visit the SUGUK site to download my presentation, please register and attend one of the forthcoming events whilst you’re there – it’s an excellent way to improve your knowledge and meet others from the SharePoint community.

Wednesday, 1 June 2011

Removing features from a content database in SharePoint 2010 using PowerShell

The great thing about the Health Analyzer in SharePoint 2010 is that it will report on a number of potential issues with the server farm, which may cause a problem later whilst applying a cumulative update or service pack. Resolving these issues in advance will help to prevent an update failing when you run the SharePoint Configuration Wizard.

One of these problems may occur when a solution is removed from the farm before the corresponding features were deactivated from site collections and sites. The Health Analyzer will place this issue in the “Configuration” category with the title “Missing server side dependencies”.

Missing server side dependencies

The error message reported will look similar to this one:

[MissingFeature] Database [SharePoint_Content_Portal] has reference(s) to a missing feature: Id = [8096285f-1463-42c7-82b7-f745e5bacf29], Name = [My Feature], Description = [], Install Location = [Test-MyFeature]. The feature with Id 8096285f-1463-42c7-82b7-f745e5bacf29 is referenced in the database [SharePoint_Content_Portal], but is not installed on the current farm. The missing feature may cause upgrade to fail. Please install any solution which contains the feature and restart upgrade if necessary.

As shown above, this message reports a content database name (SharePoint_Content_Portal) and feature ID (8096285f-1463-42c7-82b7-f745e5bacf29), but not the sites or site collections where the feature exists. In addition to this, even if you did know where the feature was activated, it will not appear anywhere in the UI for you to deactivate because the solution has been removed from the farm.

The following PowerShell script will interrogate a specified content database and feature ID and do two things:

  1. Produce a report in the PowerShell console showing which sites or site collections contain the offending feature.
  2. Forcibly deactivate the feature from the applicable sites or site collections.

Note: Whilst this article applies specifically to the scenario of deactivating features from removed solutions reported by the Health Analyzer, I have decided to write the script so that it deactivates any specified feature from sites and site collections – not just those missing from the farm. This allows the script to be used in other scenarios, too.

To use the script, run these functions in a PowerShell console with the SharePoint 2010 add-ons loaded:

function Remove-SPFeatureFromContentDB($ContentDb, $FeatureId, [switch]$ReportOnly)
{
    $db = Get-SPDatabase | where { $_.Name -eq $ContentDb }
    [bool]$report = $false
    if ($ReportOnly) { $report = $true }
   
    $db.Sites | ForEach-Object {
       
        Remove-SPFeature -obj $_ -objName "site collection" -featId $FeatureId -report $report
               
        $_ | Get-SPWeb -Limit all | ForEach-Object {
           
            Remove-SPFeature -obj $_ -objName "site" -featId $FeatureId -report $report
        }
    }
}

function Remove-SPFeature($obj, $objName, $featId, [bool]$report)
{
    $feature = $obj.Features[$featId]
   
    if ($feature -ne $null) {
        if ($report) {
            write-host "Feature found in" $objName ":" $obj.Url -foregroundcolor Red
        }
        else
        {
            try {
                $obj.Features.Remove($feature.DefinitionId, $true)
                write-host "Feature successfully removed from" $objName ":" $obj.Url -foregroundcolor Red
            }
            catch {
                write-host "There has been an error trying to remove the feature:" $_
            }
        }
    }
    else {
        #write-host "Feature ID specified does not exist in" $objName ":" $obj.Url
    }
}

You now have two options for using these functions. If you just want to produce a report in the console showing which sites and site collections contain the feature, type the following (note the ReportOnly switch on the end):

Remove-SPFeatureFromContentDB -ContentDB "SharePoint_Content_Portal" -FeatureId "8096285f-1463-42c7-82b7-f745e5bacf29" –ReportOnly

This command will step through all sites and site collections and display the following message whenever it finds the feature specified:

Feature found in site : http://portal/site

If you want to go ahead and remove the feature from all sites and site collections in the content database, type the same command without the ReportOnly switch on the end:

Remove-SPFeatureFromContentDB -ContentDB "SharePoint_Content_Portal" -FeatureId "8096285f-1463-42c7-82b7-f745e5bacf29"

Running this command will step through all sites and site collections, remove the feature specified, and display the following output:

Feature successfully removed from site : http://portal/site

You should now be able to reanalyse the “Missing server side dependencies” issue in the Health Analyzer to clear the problem (providing there are no other issues reported under that title, of course!).

Note: If you found this article looking for information on how to diagnose MissingSetupFile issues in the SharePoint Health Analyzer, rather than the MissingFeature issue, then have a look at my follow up article. For information on troubleshooting MissingWebPart and MissingAssembly errors, take a look at this article.