Pages

18 October 2011

Solving [MissingSetupFile] errors from SharePoint Health Analyzer

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 Analyzer

The 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:

Anonymous said...

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

Etienne said...

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.

Anonymous said...

Perfect!

Thanks Etienne

Martin

Anonymous said...

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".

kurbycar32 said...

^^ Yea i got the same thing. is adding the $list.delete() command the same as deleting the row from the sql database?

Etienne said...

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...

KansasCoder said...

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!

Etienne said...

Hello Kansas.

I suggest you to check the site recycle bin.

Cheers.
Etienne.

Anonymous said...

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().

Etienne said...

That's right, thanks for noticing it, i've updated the example.

Anonymous said...

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

Etienne said...

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.

Marcel said...

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?

David Tappan said...

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

Etienne said...

Hello David,

Maybe you did not format the imput txt file correctly. Each line should contain the feature and dbname separated with semicolon.

Anonymous said...

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

fabien said...

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

Matthew said...

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?

Anonymous said...

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

Etienne said...

John, make sure the content of the missing.ps1 script start with the param section. You should not put anything before the param statement.

Anonymous said...

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

Matthew said...

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.

Chetan Chudasama said...

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.

treeSeeker said...

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!

Jay Woods said...
This comment has been removed by the author.
Jay said...

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.

Robert P. Calfee said...

I am William..I just browsing through some blogs and came across yours!Excellent blog, good to see someone actually uses for quality posts.Your site kept me on for a few minutes unlike the rest :)Keep up the good work!Thanks for sharing a important information on sharepoint

Anonymous said...

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.

Anonymous said...

Also you may be deleting the file, but not the file which is referencing the file you deleted.

Francis said...

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

Keith Culpepper said...
This comment has been removed by the author.
mhbotha said...

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?

Mikhail Pushin said...

Thanks Etienne! It works!

Jeremy said...

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?

swtjen01 said...

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.

mareddy tirupathi said...

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

Anonymous said...

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!

Anonymous said...

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.

Anonymous said...

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.

Anonymous said...

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?

Lee Diggins said...

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

JayaRaja said...

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

Tomislav Tasic said...

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

Cathi said...

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.

Etienne said...

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 ;-)

Micheal Stephenson said...

This post is a godsend. Inherited a SharePoint System with none of the original WSPs and no support files. Thank you for this.

Olga Mikheyeva said...

Great post! Thanks these saved lots of my time!

David h said...

Nice explanation with snapshots, keep it up for more Sharepoint online training

Post a Comment