ISSUE DESCRIPTION:
After a SharePoint 2007 Migration to SharePoint 2010, on the Central Administration, the SharePoint Health Analyzer is generating the critical event [Missing server side dependencies] : And the event details is generating a lot of [MissingSetupFile] errors, examples:
[MissingSetupFile] File [Features\DocumentReviewDocsForReviewList\docsforreview\repair.aspx] is referenced [5] times in the database [Sharepoint_80_Content_04], 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_80_Content_04], but are not installed on the current farm. Please install any feature or solution which contains these files.
[MissingSetupFile] File [Features\DocumentReviewDocsForReviewList\docsforreview\Upload.aspx] is referenced [5] times in the database [Sharepoint_80_Content_04], 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_80_Content_04], but are not installed on the current farm. Please install any feature or solution which contains these files.
[MissingSetupFile] File [Features\DocumentReviewModules\default.aspx] is referenced [5] times in the database [Sharepoint_80_Content_04], 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_80_Content_04], but are not installed on the current farm. Please install any feature or solution which contains these files
[MissingSetupFile] File [Features\InfoPathFormViewer_c9ca3d89-c724-4265-9246-70ef8bf8bdbf\InfoPathFormViewer.webpart] is referenced [2] times in the database [Sharepoint_80_Content_04], 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_80_Content_04], but are not installed on the current farm. Please install any feature or solution which contains these files.
[MissingSetupFile] File [Features\KnowledgeBaseKnowledgeBaseList\kbase\repair.aspx] is referenced [2] times in the database [Sharepoint_80_Content_04], 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_80_Content_04], but are not installed on the current farm. Please install any feature or solution which contains these files.
[MissingSetupFile] File [Features\KnowledgeBaseKnowledgeBaseList\kbase\Upload.aspx] is referenced [2] times in the database [Sharepoint_80_Content_04], 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_80_Content_04], but are not installed on the current farm. Please install any feature or solution which contains these files.
ROOT CAUSE:
These events are logged because the migrated SharePoint 2010 Sites contains some references to custom Feature files and the linked feature are not installed in the Farm.In my case, I have tried to clean up the SharePoint 2007 Sites before the migration by disabling and uninstalling the unused features, but most of the times, the feature custom files are not getting removed correctly.
SOLUTION:
The easy solution is obviously to install the features related to those files, but if you are in the same situation as me, you don't really need the features anymore and you just want the database to be clean and get rid of these events.To safely remove the files, we need to be able to identify their specific location on the Farm, I have created an automated PowerShell script based on Phil's article (Thanks Phil), this script will get all the required information for you:
param (
[string]$DBserver = $(throw "Missing server name (please use -dbserver [dbserver])"),
[string]$path = $(throw "Missing input file (please use -path [path\file.txt])")
)
#Set Variables
$input = @(Get-Content $path)
#Addin SharePoint2010 PowerShell Snapin
Add-PSSnapin -Name Microsoft.SharePoint.PowerShell
#Declare Log File
Function StartTracing
{
$LogTime = Get-Date -Format yyyy-MM-dd_h-mm
$script:LogFile = "MissingSetupFileOutput-$LogTime.txt"
Start-Transcript -Path $LogFile -Force
}
#Declare SQL Query 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]
}
#Declare the GetFileUrl function
function GetFileUrl ($filepath, $DBname)
{
#Define SQL Query and set in Variable
$Query = "SELECT * from AllDocs where SetupPath = '"+$filepath+"'"
#Runing SQL Query to get information about the MissingFiles and store it in a Table
$QueryReturn = @(Run-SQLQuery -SqlServer $DBserver -SqlDatabase $DBname -SqlQuery $Query | select Id, SiteId, DirName, LeafName, WebId, ListId)
foreach ($event in $QueryReturn)
{
if ($event.id -ne $null)
{
$site = Get-SPSite -Limit all | where { $_.Id -eq $event.SiteId }
#get the URL of the Web:
$web = $site | Get-SPWeb -Limit all | where { $_.Id -eq $event.WebId }
#Write the SPWeb URL to host
Write-Host $filepath -nonewline -foregroundcolor yellow
Write-Host ";" -nonewline
write-host $web.Url -NoNewline -foregroundcolor green
#get the URL of the actual file:
$file = $web.GetFile([Guid]$event.Id)
#Write the relative URL to host
write-host "/" -nonewline -foregroundcolor green
write-host $file.Url -foregroundcolor green
}
}
}
#Start Logging
StartTracing
#Log the CVS Column Title Line
write-host "MissingSetupFile;Url" -foregroundcolor Red
foreach ($event in $input)
{
$filepath = $event.split(";")[0]
$DBname = $event.split(";")[1]
#call Function
GetFileUrl $filepath $dbname
}
#Stop Logging
Stop-Transcript
Paste the above code in a PowerShellScript file, like [MissingSetupFileDetails.ps1] and copy it on your local SharePoint Server Drive.
Launch the script from a Windows Powershell Cmd Prompt using the following parametters:
.\MissingSetupFileDetails.ps1 -DBserver <SQLServerName> -path <fullpath\missingfiles.txt>
[path\missingfiles.txt] is a input file you need to create based on the [MissingServerFile] errors that you get on the SharePoint Health AnalyzerThe input.txt file should be formated like this (FeaturesFilePath;ContentDatabase), example:
Features\DocumentReviewDocsForReviewList\docsforreview\repair.aspx;Sharepoint_80_Content_01
Features\DocumentReviewDocsForReviewList\docsforreview\Upload.aspx;Sharepoint_80_Content_01
Features\DocumentReviewModules\default.aspx;Sharepoint_80_Content_01
Features\InfoPathFormViewer_c9ca3d89-c724-4265-9246-70ef8bf8bdbf\InfoPathFormViewer.webpart;Sharepoint_80_Content_02
Features\KnowledgeBaseKnowledgeBaseList\kbase\repair.aspx;Sharepoint_80_Content_03
Features\KnowledgeBaseKnowledgeBaseList\kbase\Upload.aspx;Sharepoint_80_Content_03
After execution, the script generates a CSV output file in the same folder with details about the file location.
Note: If you want to get rid of all files unused, update the above script by adding the line $file.delete() after the line write-host $file.Url -foregroundcolor green in the IF statement
(to be used at your own risk - I would strongly recommend to first analyse the CSV generated (excel) before updating the script with the delete option, to avoid removing important files.)
------------
For [MissingWebPart] events, please check my next article
For [MissingAssembly] events, please check next article
For [MissingFeature] events, feel free to use the great tool FeatureAdmin, it can scan the whole farm and remove the corrupted feature references.
48 comments:
Nice post...best I've seen on these issues so far. Any chance you can modify your scripts to modify the MissingWebPart and MissingSetUpFiles
Martin
Hello Martin,
Do you mean if it's possible to delete the objects within the script ?
If this is your question then yes it's possible:
In the above script code, after the line :
$file = $web.GetFile([Guid]$event.Id)
Create a new entry with this:
$file.delete()
This will delete all the missingsetupfiles detected.
But I would recommend to first analyse the CSV generated (excel) to avoid removing important files.
Cheers.
Etienne.
Perfect!
Thanks Etienne
Martin
I tried adding the line $list.delete() after the line write-host $file.Url -foregroundcolor green in the IF statement. When running in Powershell received error "You cannot call a method on a null-valued expression".
^^ Yea i got the same thing. is adding the $list.delete() command the same as deleting the row from the sql database?
If you are receiving the error "You cannot call a method on a null-valued expression" when running the script, this may happen if the script if trying to delete a file which is present on the recycle bin.
The SharePoint Event generated is also scanning the file on recycle bin...
Hi Etienne, Your script really made it easy for me to find the exact location of the missing files. I went to the sites and manually removed the files that were missing from the interface. most of them were images that were used on an old 2007 masterpage which didn't make it over. After I removed them I reran the Health Analyzer and they still showed up in the results (Missing Server Side Dependencies). TO be sure I wasn't losing my mind I checked in the db and lo and behold the file was still there in AllDocs! I checked the Site and the image was not in the list of images any more. Any idea what's going? How can I remove these references without removing the entire site or list?
Thank you!
Hello Kansas.
I suggest you to check the site recycle bin.
Cheers.
Etienne.
Thank you for a great post! Are you sure you don't mean to add $file.delete() to remove the file? Your example has $list.delete().
That's right, thanks for noticing it, i've updated the example.
After run the Script im get the flowing message
Features\OntolicaStyleGallery\osg\Upload.aspx;http://infonet-s/Exception calling "Delete" with "0" argument(s): "Unable
to find the specified file."
At C:\Users\admin.jwb\Documents\MissingSetupFileDetails.ps1:53 char:22
+ $file.delete <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Please try the re-analyse option in the health analyser event to make sure the files are still showing. If yes then launch the script without the $file.delete() line and check the corresponding site recycle bin.
I keep on getting the following error:
$site = Get-SPSite -Limit all | where { $_.Id -eq "guid_siteId" }
$site =
$web = $site | Get-SPWeb -Limit all | where { $_.Id -eq "guid_webId" }
Get-SPWeb : Syntax Error: Either provide a full Url or an SPSite object.
Any idea?
I keep getting an error when running this script, and I don't know why, can you help? The error is:
MissingSetupFile;Url
Exception calling "Fill" with "1" argument(s): "Invalid object name 'AllDocs'."
At C:\missingsetupfiles.ps1:27 char:20
+ $SqlAdapter.Fill <<<< ($DataSet)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Hello David,
Maybe you did not format the imput txt file correctly. Each line should contain the feature and dbname separated with semicolon.
I've emptied the recycle bin for the site where the files are being found, reanalyzed with health analyzer and am still getting error missing setup files error and the error like this one:
Features\OntolicaStyleGallery\osg\Upload.aspx;http://infonet-s/Exception calling "Delete" with "0" argument(s): "Unable
to find the specified file."
At C:\Users\admin.jwb\Documents\MissingSetupFileDetails.ps1:53 char:22
+ $file.delete <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Hello, very usefull post, especially when a migration brings more than 600 MissingSetupFile references ...
I've a little bit extended the script for "more" automation.
First a script for extracting MissingSetupFile from all content databases, then export as CSV through Export-CSV
http://pastebin.com/pBB3KRr5
Then a small edits on MissingSetupFileDetails.ps1 for using Import-CSV
http://pastebin.com/0y06mvDa
glad if it helps
Great Script! I have completely cleaned up a Development Farm with one exception: Silverlight Assets deployed as part of a Field Control. "Features\SP.MobileFieldControl_Map Address\ClientBin\AddressMap.xap" I have deleted the Site Collection and Retracted the Solution, but I still have 2 references in the database. They point to the deleted site. (I have removed the site from the Content DB with Remove-SPDeletedSite. Any Ideas?
Hello, I a fairly new to powershell. So I am not sure what is wrong but when I try to run this script as above it throws the missing input file error. Now I have followed the about closely. I have tried it on a number of servers even my SQL server. The full error is below. The command I am using is : .\missing.ps1 -DBserver buswsql2 -path c:\pathfile.txt
Any help would be greatly appreciated.
-John
Invalid assignment expression. The left hand side of an assignment operator needs to be something that can be assigned
to like a variable or a property.
At C:\missing.ps1:5 char:19
+ [string]$path = <<<< $(throw "Missing input file (please use -path [path\file.txt])")
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : InvalidLeftHandSide
John, make sure the content of the missing.ps1 script start with the param section. You should not put anything before the param statement.
Thanks Etienne, I found when I selected the script text that there was some extra stuff copied over. Now I am try to diagnose connecting to sql issues. Thanks for the script.
-john
After a few days my AddressMap.xap file issue resolved itself. Must have been a timer job that did the final clean up. It's a mystery.
Hi there,
I am also getting the below error
Exception calling "Fill" with "1" argument(s): "Invalid object name 'AllDocs'."
At C:\scripts\MissingSetupFileDetails.ps1:27 char:20
+ $SqlAdapter.Fill <<<< ($DataSet)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
would you be able to provide an example of the script -
.\MissingSetupFileDetails.ps1 -DBserver -path
for the below error with a database server name: "uk-spbe01"
[MissingSetupFile] File [Features\Bamboo.AdvancedSearch\WebParts\Bamboo.AdvancedSearch.dwp] is referenced [2] times in the database [WSS_Content_Geonet_Intranet_Americas], but is not installed on the current farm. Please install any feature/solution which contains this file.
Fabien / Etienne
I've used Fabien's additional powershell scripts to great satisfaction except for one final issue. All of the missing dependencies have been removed from the database but there are a few that still show up in health analyzer.
So I guess they are on the server?
How dow I remove these? (NOTE: All site recycle bins are empty)
Thanks ahead!
Works well if you add the delete file line in there. But if you go and delete individually out of all recycle bins, still shows up in analyzer, very frustrating. The others that I deleted with the script, didn't show back up in the analyzer. Very very strange.
Remember SharePoint 2010 has a 2 stage recycle bin! Emptying the end user recycle bin will still not delete the file till its deleted from the site collection recycle bin.
Also you may be deleting the file, but not the file which is referencing the file you deleted.
Hi All
Great post but im having some issues
Transcript started, output file is MissingSetupFileOutput-2013-02-10_2-32.txt
MissingSetupFile;Url
Exception calling "Fill" with "1" argument(s): "Invalid object name 'AllDocs'."
At C:\MissingSetupFileDetails.ps1:27 char:20
+ $SqlAdapter.Fill <<<< ($DataSet)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Transcript stopped, output file is MissingSetupFileOutput-2013-02-10_2-32.txt
Hi Etienne
I'm getting a Login Failed error for the user trying to run the ps1 script. Have used both my farm account and my own which i know have full farm adnDB access.
Exception calling "Fill" with "1" argument(s): "Login failed for user 'AFRICA\Morne.Botha'."
At C:\MissingSetup.ps1:27 char:20
+ $SqlAdapter.Fill <<<< ($DataSet)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Exception calling "Fill" with "1" argument(s): "Login failed for user 'AFRICA\Morne.Botha'."
At C:\MissingSetup.ps1:27 char:20
+ $SqlAdapter.Fill <<<< ($DataSet)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Any ideas?
Thanks Etienne! It works!
I am getting a ton of errors when running the script. A bunch of the problem features have been removed but more than half remain.
Features\MossTraining\MasterPages\StkHome.master;You cannot call a method on a null-valued expression.
At C:\tools\MissingSetupFileDetailsAndDelete.ps1:50 char:10
+ $file = $web.GetFile([Guid]$event.Id)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
I have checked the recyclebin both end user and admin and do not see any of the objects. Thoughts?
I love your script and it has always worked like a charm for me. However I just migrated over a site from 2007 to 2010 and when I try to run the script it shows: Get-spweb: Access is denied. I am dbo of the content database so I'm not sure why its failing to run.
Iam getting Error run the same script with our parameters can you please help me
PS E:\FeatureAdmin2010> .\MissingSetupFileDetails.ps1 -DBserver USETLCVW104 -pat
h "E:\FeatureAdmin2010\missingfiles.txt"
Get-Content : Cannot find path 'E:\FeatureAdmin2010\missingfiles.txt' because i
t does not exist.
At E:\FeatureAdmin2010\MissingSetupFileDetails.ps1:5 char:25
+ $input = @(Get-Content <<<< $path)
+ CategoryInfo : ObjectNotFound: (E:\FeatureAdmin2010\missingfile
s.txt:String) [Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetCo
ntentCommand
It's incredible! I had a big problem with SharePoint missing server side dependencies...I typed Etienne Powershell Scripts in Google and that simply solved my problem!!! He saved my job!
For those having access denied when running the script, try grating full control access to the account you are using at the web application level.
Will this script work for 2013. I am trying to run it however the file keeps coming empty and I know there are features missing.
Great Script however I still have one that when I run the script I get the following error.
Exception calling "Delete" with "0" argument(s): "This item cannot be deleted because it is still referenced by other pages."
I have 2 instances of this in the same database. There are no other pages using this solution. Is there a way to override this and delete it anyway?
Etienne, awesome script, many thanks.
I've just used this to clean-up my 2013 development instance. I used this in conjunction with the delete items from recycle bins: http://gallery.technet.microsoft.com/office/SharePoint-PowerShell-3bdd0d3a
Kind regards,
Lee
Added a quick functionality to the script to prompt user if they wanna delete it or not and then remove upon choice
param (
[string]$DBserver = $(throw "Missing server name (please use -dbserver [dbserver])"),
[string]$path = $(throw "Missing input file (please use -path [path\file.txt])")
)
#Set Variables
$input = @(Get-Content $path)
#Addin SharePoint2010 PowerShell Snapin
Add-PSSnapin -Name Microsoft.SharePoint.PowerShell
#Declare Log File
Function StartTracing
{
$LogTime = Get-Date -Format yyyy-MM-dd_h-mm
$script:LogFile = "MissingSetupFileOutput-$LogTime.txt"
Start-Transcript -Path $LogFile -Force
}
#Declare SQL Query 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]
}
#Declare the GetFileUrl function
function GetFileUrl ($filepath, $DBname)
{
#Define SQL Query and set in Variable
$Query = "SELECT * from AllDocs where SetupPath = '"+$filepath+"'"
#Runing SQL Query to get information about the MissingFiles and store it in a Table
$QueryReturn = @(Run-SQLQuery -SqlServer $DBserver -SqlDatabase $DBname -SqlQuery $Query | select Id, SiteId, DirName, LeafName, WebId, ListId)
$TitleDeleteHeader = "Delete ???"
$TitleDeleteMessage = "Would you like to delete this file"
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
"Deleted the file..."
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
"Did not delete the file..."
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
foreach ($event in $QueryReturn)
{
if ($event.id -ne $null)
{
$site = Get-SPSite -Limit all | where { $_.Id -eq $event.SiteId }
#get the URL of the Web:
$web = $site | Get-SPWeb -Limit all | where { $_.Id -eq $event.WebId }
#Write the SPWeb URL to host
Write-Host $filepath -nonewline -foregroundcolor yellow
Write-Host ";" -nonewline
write-host $web.Url -NoNewline -foregroundcolor green
#get the URL of the actual file:
$file = $web.GetFile([Guid]$event.Id)
#Write the relative URL to host
write-host "/" -nonewline -foregroundcolor green
write-host $file.Url -foregroundcolor green
$result = $host.ui.PromptForChoice($title, $message, $options, 0)
switch ($result)
{
0 {
write-host "Removing File... " $file.Url
$file.delete()
Write-host "Deleted the file"
}
1 {"Skipping and moving to the next file in the queue"}
}
}
}
}
#Start Logging
StartTracing
#Log the CVS Column Title Line
write-host "MissingSetupFile;Url" -foregroundcolor Red
foreach ($event in $input)
{
$filepath = $event.split(";")[0]
$DBname = $event.split(";")[1]
#call Function
GetFileUrl $filepath $dbname
}
#Stop Logging
Stop-Transcript
Great post!
Also, please before running a script add following:
"Open Central Administration - Application Management - Manage Web Applications - (select web application) - User Policy - Add Users - All zones - Next - Users: (add user with which you are logged on to the server) - check "Full Control" option - Finish".
If you do not do that you can get error described here: http://tomislavspadmin.blogspot.com/2014/08/access-is-denied-exception-from-hresult.html
I am currently having this issue with a customized master page in 2013 that we no longer wish to use. Would you say it would be safe to uninstall the feature first and then if the health analyzer reports an issue to run your script? The issue is compatibility going from 2010 to 2013 farm. I want to deactivate the feature, uninstall it, reset the master page to "seattle" default and then remove any missing files that still show up in the reports.
Yes I would say it's the safe way. Uninstall properly the feature, then reload the healthanalyser rule. If files are still orphaned then kill them with the script ;-)
This post is a godsend. Inherited a SharePoint System with none of the original WSPs and no support files. Thank you for this.
Great post! Thanks these saved lots of my time!
Nice explanation with snapshots, keep it up for more Sharepoint online training
Mine is not generating any CSV file. It generates a txt output file with very little details about the setup file. What could I be doing wrong? I double checked the script multiple times already. Your assistance will be highly appreciated.
Post a Comment