This is part of a series on SharePoint Health Report issues, because I can never remember what to do about them.
Posts in this series
Missing setup file
The warning looks like this:
Category : MissingSetupFile
Error : True
UpgradeBlocking : False
Message : File [Features\MySolution_Feature1\WebPart\WebPart.webpart]
is referenced [100] times in the database [ContentDatabaseName],
but is not installed in the current farm. Please install any
feature/solution which contains this file.
Remedy : One or more files are referenced in the database [ContentDatabaseName],
but are not installed in the current farm. Please install any
feature or solution which contain these files.
The solution is either to install the missing dependency - as the warning suggests, or to remove the offending reference. To find the offending reference, a query to the database has to be utilized:
select Id, SiteId, DirName, LeafName, WebId, ListId from AllDocs with (NOLOCK)
where SetupPath = 'Features\MySolution_Feature1\WebPart\WebPart.webpart'
SetupPath
should be equal to the path given in the warning.
The resulting lines will show all elements still in SharePoint that reference the missing file.
Now, the elements can be deleted by using PowerShell:
$site = Get-SPSite -Identity <SiteID from SQL result>
$web = Get-SPWeb -Identity <WebID from SQL result> -Site $site
$file = $web.GetFile([guid]"<Id from SQL result>")
$file.Delete()
Make sure that the file being delete here is really no longer needed!
I have created a little script to help with finding the Ids and deleting the entries:
#Requires -PSSnapin Microsoft.SharePoint.PowerShell
<#
.Synopsis
Deletes all references to files that have missing SetupFiles
USE WITH CAUTION!
#>
[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory=$true)]
[string]$ContenDatabase,
[Parameter(Mandatory=$true)]
[string]$MissingFileName,
[switch]$Force
)
$ErrorActionPreference="Stop"
$contentDb = Get-SPContentDatabase $ContenDatabase
$data = new-object System.Data.DataSet
try {
$connection = new-object System.Data.SqlClient.SqlConnection -ArgumentList @($contentDb.DatabaseConnectionString)
$query = "select Id, SiteId, WebId from AllDocs with (NOLOCK) where SetupPath like '$MissingFileName'"
$command = new-object System.Data.SqlClient.SqlCommand -ArgumentList @($query, $connection)
$connection.Open()
$adapter = new-object System.Data.SqlClient.SqlDataAdapter -ArgumentList @($command)
$adapter.Fill($data) | Out-Null
} finally {
$connection.dispose()
}
$data.Tables[0] | % {
try {
$web = Get-spweb $_.WebId -Site $_.SiteId
$file = $web.GetFile($_.Id)
if($PSCmdlet.ShouldProcess($file.ServerRelativeUrl)){
if($Force.isPresent -or $PSCmdlet.ShouldContinue("Delete $($file.ServerRelativeUrl) ?", "Confirm")) {
$file.Delete()
}
}
} finally {
$web.Dispose()
}
}