После установки обновлений Sharepoint необходимо проводить процедуру обновления средством Мастера настройки продуктов Sharepoint, выполнение которой заканчивалось всегда ошибкой, указывающей что в БД WSS_Content имеются MissingSetupFiles, MissingWebpart, MissingFeatures.
Сначала необходимо запустить файл Step 1.ps1, который сформирует файл с указанием всех MissingSetupFiles, MissingWebpart, MissingFeatures.
step 1.ps1
$wa = Get-SPWebApplication "https://portal.pac.ru"
$outputPath = "C:\\Users\spfarm\Desktop\Cleanup_missing_features\Test_Wss_Content_MissingAssembly_{0}.txt" -f (Get-Date -Format hhmmss)
$dbName = "WSS_Content"
$slqServer = "sharSQL"
Test-SPContentDatabase -Name $dbName -WebApplication $wa -ServerInstance $slqServer -ShowLocation:$true -ExtendedCheck:$false | Out-File $outputPath
Для очистки MissingFeatures редактируем и запускаем файл Step 2.ps1, указываем в нем $featureID и $siteID.
step 2.ps1
$featureID = "75e8e0cf-9b94-4803-93bb-6a9bb93995ae"
$siteID = "f2f6396a-6e72-4747-b5c0-3c7efd604dab"
#Display site information
$site = Get-SPSite $siteID
Write-Host "Checking Site:" $site.Url
#Remove the feature from all subsites
ForEach ($web in $Site.AllWebs)
{
If($web.Features[$featureID])
{
Write-Host "`nFound Feature $featureID in web:"$Web.Url"`nRemoving feature"
$web.Features.Remove($featureID, $true)
}
else
{
Write-Host "`nDid not find feature $featureID in web:" $Web.Url
}
}
#Remove the feature from the site collection
If ($Site.Features[$featureID])
{
Write-Host "`nFound feature $featureID in site:"$site.Url"`nRemoving Feature"
$site.Features.Remove($featureID, $true)
}
else
{
Write-Host "Did not find feature $featureID in site:" $site.Url
}
Затем редактируем Step 3.ps1, указываем в нем FeatureID в строке
Remove-SPFeatureFromContentDB -ContentDB «Wss_Content» -FeatureId «75e8e0cf-9b94-4803-93bb-6a9bb93995ae» –ReportOnly
step 3.ps1
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
}
}
Remove-SPFeatureFromContentDB -ContentDB "Wss_Content" -FeatureId "75e8e0cf-9b94-4803-93bb-6a9bb93995ae" –ReportOnly
и запускем выполнение Step 3.ps1
Так последовательно удаляется каждый MissingFeature
Для удаления MissingSetupFiles редактируем файл Remove missing setup files.ps1, указываем в нем $SetupFile
$SetupFile=»Features\TestWPproj_Feature1\TestWP\TestWP.webpart»
Remove missing setup files.ps1
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
Function Run-SQLScript($SQLServer, $SQLDatabase, $SQLQuery)
{
$ConnectionString = "Server =" + $SQLServer + "; Database =" + $SQLDatabase + "; Integrated Security = True"
$Connection = new-object system.data.SqlClient.SQLConnection($ConnectionString)
$Command = new-object system.data.sqlclient.sqlcommand($SQLQuery,$Connection)
$Connection.Open()
$Adapter = New-Object System.Data.sqlclient.sqlDataAdapter $Command
$Dataset = New-Object System.Data.DataSet
$Adapter.Fill($Dataset)
$Connection.Close()
$Dataset.Tables[0]
}
#Define configuration parameters
$Server="sharSQL"
$Database="WSS_Content"
$SetupFile="Features\TestWPproj_Feature1\TestWP\TestWP.webpart"
#Query SQL Server content Database to get information about the MissingFiles
$Query = "SELECT * from AllDocs where SetupPath like '"+$SetupFile+"'"
$QueryResults = @(Run-SQLScript -SQLServer $Server -SQLDatabase $Database -SQLQuery $Query | select Id, SiteId, WebId)
#Iterate through results
foreach ($Result in $QueryResults)
{
if($Result.id -ne $Null)
{
$Site = Get-SPSite -Limit all | where { $_.Id -eq $Result.SiteId }
$Web = $Site | Get-SPWeb -Limit all | where { $_.Id -eq $Result.WebId }
#Get the URL of the file which is referring the feature
$File = $web.GetFile([Guid]$Result.Id)
write-host "$($Web.URL)/$($File.Url)" -foregroundcolor green
$File.delete()
}
}
И запускаем для каждого MissingSetupFile
Для удаления MissingWebpart редактируем файл Remove missing webpart.ps1, указываем в нем $webPartID
$webPartID=»6817d0b2-eccd-d695-340d-82e13c030b09″
Remove missing webpart.ps1
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
Function Run-SQLScript($SQLServer, $SQLDatabase, $SQLQuery)
{
$ConnectionString = "Server =" + $SQLServer + "; Database =" + $SQLDatabase + "; Integrated Security = True"
$Connection = new-object system.data.SqlClient.SQLConnection($ConnectionString)
$Command = new-object system.data.sqlclient.sqlcommand($SQLQuery,$Connection)
$Connection.Open()
$Adapter = New-Object System.Data.sqlclient.sqlDataAdapter $Command
$Dataset = New-Object System.Data.DataSet
$Adapter.Fill($Dataset)
$Connection.Close()
$Dataset.Tables[0]
}
#Define configuration parameters
$Database="WSS_Content"
$webPartID="6817d0b2-eccd-d695-340d-82e13c030b09"
#Get the Database Server from Database
$server = (Get-SPDatabase |?{ $_.name -eq $Database}).server
#Query SQL Server content Database to get information about the MissingFiles
$Query = "SELECT distinct ID,SiteId,DirName, LeafName, WebId, ListId from dbo.AllDocs where id in (select tp_PageUrlID from dbo.AllWebParts where tp_WebPartTypeId ='$($webPartID)')"
$QueryResults = Run-SQLScript -SQLServer $Server -SQLDatabase $Database -SQLQuery $Query | select Id , SiteId, DirName, LeafName, WebId, ListId
#Iterate through results
foreach ($Result in $QueryResults)
{
if($Result.id -ne $Null)
{
$Site = Get-SPSite -Limit all | where { $_.Id -eq $Result.SiteId }
$Web = $Site | Get-SPWeb -Limit all | where { $_.Id -eq $Result.WebId }
#Get the URL of the file which is referring the web part
$File = $web.GetFile([Guid]$Result.Id)
write-host "$($Web.URL)/$($File.Url)" -foregroundcolor green
$File.delete()
}
}
И запускаем для каждого MissingWebpart