Friday, April 28, 2017

Sharepoint - Microsoft.Office.Server.UserProfiles.UserProfileApplicationNotAvailableException: UserProfileApplicationNotAvailableException_Logging :: UserProfileApplicationProxy.ApplicationProperties ProfilePropertyCache does not have


Exception on UPS Service
Exception instantiating UserProfileManager, exception is Microsoft.Office.Server.UserProfiles.UserProfileApplicationNotAvailableException: UserProfileApplicationNotAvailableException_Logging :: UserProfileApplicationProxy.ApplicationProperties ProfilePropertyCache does not have afdf55d6-5c22-488d-80bb-4dd0db6c5907     at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_ApplicationProperties()   
at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.CheckAdministrationAccess(UserProfileApplicationAdminRights rights, Boolean requireAllRights)   
at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.CheckAdministrationAccess(UserProfileApplicationAdminRights rights)   
at Microsoft.Office.Server.UserProfiles.ProfileManagerBase.CanManagePeople(UserProfileApplicationProxy userProfileApplicationProxy)   
at Microsoft.Office.Server.Administration.UserProfileApplicationProxy.get_IsProfileAdmin()   
at Microsoft.Office.Server.UserProfiles.ProfileManagerBase.get_IsProfileAdmin()   
at Microsoft.Office.Server.UserProfiles.UserProfileManager..ctor(SPServiceContext serviceContext, Boolean IgnoreUserPrivacy, Boolean backwardCompatible)   
at Microsoft.Office.Server.UserProfiles.UserProfileManager..ctor()   
at Microsoft.Office.Server.UserProfiles.UserProfileService.InitProfileManager()
Resolution
The error that we were seeing in ULS (UserProfileApplicationProxy.ApplicationProperties ProfilePropertyCache does not have afdf55d6-5c22-488d-80bb-4dd0db6c5907).
afdf55d6-5c22-488d-80bb-4dd0db6c5907 is one of the Machine Keys. Since the administrators did not have proper access to the keys, the error was being thrown.
 

Navigate too - C:\ProgramData\Microsoft\Crypto\RSA
· Right Click Machine Keys
- Properties > Security > Advanced > Change permissions > Adminsitrators > Edit
   - Set "Apply To" as "This folder only"
         - This Folder Only = Special Permissions
·                      Special Permissions has full control + additional permissions
-  Apply To value was set too "This folder, subfolder, and files"
                  -  Denotes Full control only
















Thursday, April 27, 2017

Powershell – StopSharePointTimerServicesInFarm –ClearTimerCache – DeleteXmlFilesFromConfigCache - StartSharePointTimerServicesInFarm

 

# Clear the SharePoint Timer Cache
#
##
# Added loading of SharePoint Snapin for Powershell. Also this script only queries
# the SharePoint servers.

# Output program information
Write-Host -foregroundcolor White ""
Write-Host -foregroundcolor White "Clear SharePoint Timer Cache"

#**************************************************************************************
# Constants
#**************************************************************************************
Set-Variable timerServiceName -option Constant -value "SPTimerV4"
Set-Variable timerServiceInstanceName -option Constant -value "Microsoft SharePoint Foundation Timer"

#**************************************************************************************
# Functions
#**************************************************************************************
#<summary>
# Loads the SharePoint Powershell Snapin.
#</summary>
Function Load-SharePoint-Powershell
{
    If ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
    {
            Write-Host -ForegroundColor White " - Loading SharePoint Powershell Snapin"
        Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction Stop
    }
}

#<summary>
# Stops the SharePoint Timer Service on each server in the SharePoint Farm.
#</summary>
#<param name="$farm">The SharePoint farm object.</param>
function StopSharePointTimerServicesInFarm($farm)
{
Write-Host ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm)
{
foreach($instance in $server.ServiceInstances)
{
# If the server has the timer service then stop the service
if($instance.TypeName -eq $timerServiceInstanceName)
{
[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Stop '$timerServiceName' service on server: "
Write-Host -foregroundcolor Gray $serverName

$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$timerServiceName'"
sc.exe \\$serverName stop $timerServiceName > $null

# Wait until this service has actually stopped
WaitForServiceState $serverName $timerServiceName "Stopped"

break;
}
}
}

Write-Host ""
}

#<summary>
# Waits for the service on the server to reach the required service state.
# This can be used to wait for the "SharePoint 2010 Timer" service to stop or to start
#</summary>
#<param name="$serverName">The name of the server with the service to monitor.</param>
#<param name="$serviceName">The name of the service to monitor.</param>
#<param name="$serviceState">The service state to wait for, e.g. Stopped, or Running.</param>
function WaitForServiceState([string]$serverName, [string]$serviceName, [string]$serviceState)
{
Write-Host -foregroundcolor DarkGray -NoNewLine "Waiting for service '$serviceName' to change state to $serviceState on server $serverName"

do
{
Start-Sleep 1
Write-Host -foregroundcolor DarkGray -NoNewLine "."
$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$serviceName'"
}
while ($service.State -ne $serviceState)

Write-Host -foregroundcolor DarkGray -NoNewLine " Service is "
Write-Host -foregroundcolor Gray $serviceState
}

#<summary>
# Starts the SharePoint Timer Service on each server in the SharePoint Farm.
#</summary>
#<param name="$farm">The SharePoint farm object.</param>
function StartSharePointTimerServicesInFarm($farm)
{
Write-Host ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm)
{
foreach($instance in $server.ServiceInstances)
{
# If the server has the timer service then start the service
if($instance.TypeName -eq $timerServiceInstanceName)
{
[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Start '$timerServiceName' service on server: "
Write-Host -foregroundcolor Gray $serverName

$service = Get-WmiObject -ComputerName $serverName Win32_Service -Filter "Name='$timerServiceName'"
sc.exe \\$serverName start $timerServiceName > $null

WaitForServiceState $serverName $timerServiceName "Running"

break;
}
}
}

Write-Host ""
}

#<summary>
# Removes all xml files recursive on an UNC path
#</summary>
#<param name="$farm">The SharePoint farm object.</param>
function DeleteXmlFilesFromConfigCache($farm)
{
Write-Host ""
Write-Host -foregroundcolor DarkGray "Delete xml files"

[string] $path = ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm)
{
foreach($instance in $server.ServiceInstances)
{
# If the server has the timer service delete the XML files from the config cache
if($instance.TypeName -eq $timerServiceInstanceName)
{
[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Deleting xml files from config cache on server: "
Write-Host -foregroundcolor Gray $serverName

# Remove all xml files recursive on an UNC path
$path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\*.xml"
Remove-Item -path $path -Force

break
}
}
}

Write-Host ""
}

#<summary>
# Clears the SharePoint cache on an UNC path
#</summary>
#<param name="$farm">The SharePoint farm object.</param>
function ClearTimerCache($farm)
{
Write-Host ""
Write-Host -foregroundcolor DarkGray "Clear the cache"

[string] $path = ""

# Iterate through each server in the farm, and each service in each server
foreach($server in $farm)
{
foreach($instance in $server.ServiceInstances)
{
# If the server has the timer service then force the cache settings to be refreshed
if($instance.TypeName -eq $timerServiceInstanceName)
{
[string]$serverName = $server.Name

Write-Host -foregroundcolor DarkGray -NoNewline "Clearing timer cache on server: "
Write-Host -foregroundcolor Gray $serverName

# Clear the cache on an UNC path
# 1 = refresh all cache settings
$path = "\\" + $serverName + "\c$\ProgramData\Microsoft\SharePoint\Config\*-*\cache.ini"
Set-Content -path $path -Value "1"

break
}
}
}

Write-Host ""
}

#**************************************************************************************
# Main script block
#**************************************************************************************

# Load SharePoint Powershell Snapin
Load-SharePoint-Powershell

# Get the local farm instance
$farm = Get-SPServer | where {$_.Role -match "Application"}

# Stop the SharePoint Timer Service on each server in the farm
StopSharePointTimerServicesInFarm $farm

# Delete all xml files from cache config folder on each server in the farm
DeleteXmlFilesFromConfigCache $farm

# Clear the timer cache on each server in the farm
ClearTimerCache $farm

# Start the SharePoint Timer Service on each server in the farm
StartSharePointTimerServicesInFarm $farm

Friday, April 21, 2017

SharePoint– Add/Upload MasterPage/Document in to Sharepoint Library from Powershell

 

$approveComment="Approved"
$logfile = "UploadMasterPage_$(get-date -f yyyyMMdd_hhmmss).log"
$spsite = new-object Microsoft.Sharepoint.SPSite($webAppUrl);
$web = $spsite.RootWeb;
$masterPageList = ($web).GetFolder("Master Page Gallery")
$filesfolde = Split-Path $script:MyInvocation.MyCommand.Path

$masterPageLocalDir = $filesfolde + "\Docs"
#For upload all files in document library from file system
foreach ($file in Get-ChildItem $masterPageLocalDir)
  {
    $web.AllowUnsafeUpdates=$true;
try
{
    if ([Microsoft.SharePoint.Publishing.PublishingSite]::IsPublishingSite($spsite))
    {
   
    $stream = [IO.File]::OpenRead($file.fullname)
          $destUrl = $web.Url + "/_catalogs/masterpage/" + $file.Name;
        $masterPageFile=$web.GetFile($destUrl)
    #write-host($masterPageFile)
           if($masterPageFile.CheckOutStatus -ne "None")
        {
                #$web.AllowUnsafeUpdates  = $true;
                $masterPageList.files.Add($destUrl,$stream,$true)
                $stream.close()                       
                $masterPageFile.CheckIn($checkInComment);                       
                $masterPageFile.Publish($publishComment);               
                $masterPageFile.Approve($approveComment);
                $masterPageFile.Update();        
                $web.Update();
                $web.AllowUnsafeUpdates  = $false;
                $outputText = $file.Name+ " Master Page uploaded on $web site"
                write-output $outputText
                write-output $outputText |  out-File $logfile -Append
        }
        else
        {
                  $masterPageFile.CheckOut();
                 try{
                 $masterPageList.Files.Add($destUrl,$stream,$true)
                 }
                 catch
                 {
                 write-Output $_
                 }
                 $stream.close()                             
                 $masterPageFile.CheckIn($checkInComment);                         
                 $masterPageFile.Publish($publishComment);                         
                 $masterPageFile.Approve($approveComment);
                 $masterPageFile.Update();        
                 $web.Update();
                 $web.AllowUnsafeUpdates  = $false;
                 $outputText = $file.Name +  " Master Page uploaded on $web site"
                 write-output $outputText
                 write-output $outputText |  out-File $logfile -Append
        }
    }
    else
    {
   
        $stream = [IO.File]::OpenRead($file.fullname)
        $destUrl = $web.Url + "/_catalogs/masterpage/" +$file.Name
        $masterPageFile=$web.GetFile($destUrl)
        if($masterPageFile.CheckOutStatus -ne "None")
          {
                $masterPageList.Files.Add($destUrl,$stream,$true)
                $stream.close()                       
                $masterPageFile.CheckIn($checkInComment);                       
                $masterPageFile.Publish($publishComment);               
                $masterPageFile.Approve($approveComment);
                $masterPageFile.Update();        
                $web.Update();
                $web.AllowUnsafeUpdates  = $false;
                $outputText = $file.Name +  "Master Page uploaded on $web site"
                write-output $outputText
                write-output $outputText |  out-File $logfile -Append
           }
           else
           {
                 $masterPageFile.CheckOut();
                 $masterPageList.Files.Add($destUrl,$stream,$true)
                 $stream.close()                             
                 $masterPageFile.CheckIn($checkInComment);                         
                 $masterPageFile.Publish($publishComment);                         
                 $masterPageFile.Approve($approveComment);
                 $masterPageFile.Update();        
                 $web.Update();
                 $web.AllowUnsafeUpdates  = $false;
                 $outputText = $file.Name+ "Master Page uploaded on $web site"
                 write-output $outputText
                 write-output $outputText |  out-File $logfile -Append
          }
    }      
}
catch
{
try
       {          
        $stream = [IO.File]::OpenRead($file.fullname)
        $destUrl = $web.Url + "/_catalogs/masterpage/" + $file.Name;
        $masterPageFile=$web.GetFile($destUrl)
        if($masterPageFile.CheckOutStatus -ne "None")
           {
                $masterPageList.Files.Add($destUrl,$stream,$true)
                $stream.close()                       
                $masterPageFile.CheckIn($checkInComment);
                $masterPageFile.Update();        
                $web.Update();
                $web.AllowUnsafeUpdates  = $false;
                $outputText = $file.Name+ " Master Page uploaded on $web site"
                write-output $outputText
                write-output $outputText |  out-File $logfile -Append
          }
          else
            {

               $masterPageFile.CheckOut();
               $masterPageList.Files.Add($destUrl,$stream,$true)
               $stream.close()                       
               $masterPageFile.CheckIn($checkInComment);
               $masterPageFile.Update();        
               $web.Update();
               $web.AllowUnsafeUpdates  = $false;
               $outputText = $file.Name +" Master Page uploaded on $web site"
               write-output $outputText
               write-output $outputText |  out-File $logfile -Append
           }
       }
    catch
       {
        write-Output $_ | out-File $logfile -Append
       }    
}
}
$web.dispose();
$spsite.dispose();

Tuesday, April 18, 2017

Sharepoint 2016 – Migration from Sharepoint 2015 – Upgrade Fail - Resolve Issue For–MissingWebPart , MissingAssembly , MissingSetupFile , MissingFeature

 

Add-PsSnapin Microsoft.SharePoint.PowerShell

$SqlServer = "DBServerName";
$SqlDatabase = "ContentDB";
$WebAppURL = "WebAppUrl";

Function MissingWebPart($Message)
        {
        $webparid = ((($Message -split "\[")[1]) -split "\]")[0];
        $webparid
        $testvalue = Run-SQLQuery -SqlServer $SqlServer -SqlDatabase $SqlDatabase -SqlQuery "SELECT Id, SiteId, DirName, LeafName, WebId, ListId, tp_ZoneID, tp_DisplayName from AllDocs inner join AllWebParts on AllDocs.Id = AllWebParts.tp_PageUrlID where AllWebParts.tp_WebPartTypeID = '$webparid'"
      
        Foreach($test in $testvalue )
        {
       
        if($test.SiteId)
        {
        $test
        $site = Get-SPSite -Limit all | where { $_.Id -eq  $test.SiteId }
        $web = $site | Get-SPWeb -Limit all | where { $_.Id -eq $test.WebId }
        $web.Url
        $file = $web.GetFile([Guid]$test.Id)
        $file.ServerRelativeUrl
        $file.delete()
        }
        }
        }
       
        Function MissingSetupFile($Message)
        {
        $SetupFileid = ((($Message -split "\[")[1]) -split "\]")[0];
        $SetupFileid
        $testvalue = Run-SQLQuery -SqlServer $SqlServer -SqlDatabase $SqlDatabase -SqlQuery "SELECT  Id,SiteId,DirName,LeafName,WebId,ListId from AllDocs where SetupPath = '$SetupFileid'"
        Foreach($test in $testvalue )
        {
        if($test.SiteId)
        {
        $test

        $site = Get-SPSite -Limit all | where { $_.Id -eq  $test.SiteId }
        $web = $site | Get-SPWeb -Limit all | where { $_.Id -eq $test.WebId }
        $web.Url
        $file = $web.GetFile([Guid]$test.Id)
        $file.ServerRelativeUrl
        $file.delete()
        }
        }
        }
       
        Function MissingFeature($Message)
        {
        $Featureid = ((($Message -split "\[")[2]) -split "\]")[0];
        $Featureid
        Remove-SPFeatureFromContentDB -ContentDB $SqlDatabase -FeatureId $Featureid
       
        }

        Function MissingAssembly($Message)
        {
        $Assemblyid = ((($Message -split "\[")[1]) -split "\]")[0];
        $Assemblyid
        $testvalue = Run-SQLQuery -SqlServer $SqlServer -SqlDatabase $SqlDatabase -SqlQuery "SELECT Id, Name, SiteId, WebId, HostId, HostType from EventReceivers where Assembly = '$Assemblyid'"
        #$testvalue
        Foreach($test in $testvalue )
        {
        if($test.SiteId)
        {
        $test
        $site = Get-SPSite -Limit all | where { $_.Id -eq  $test.SiteId }
        $web = $site | Get-SPWeb -Limit all | where { $_.Id -eq $test.WebId }
        $web.Url
        $list = $web.Lists | where {$_.Id -eq $test.HostId}
        $er = $list.EventReceivers | where {$_.Id -eq $test.Id}
        $er.Delete()
        #$file.delete()
        }
        }
        }

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

            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]
        }


Test-SPContentDatabase -Name $SqlDatabase -WebApplication $WebAppURL |
    ForEach-Object {
        $Category = $_.Category
        $Message = $_.Message
 
   if($Category -contains "MissingWebPart")
   {
   write-host "MissingWebPart"
   MissingWebPart $Message;
   }
   elseif ($Category -contains "MissingAssembly")
   {
    write-host "MissingAssembly"
    MissingAssembly $Message;
   }
   elseif ($Category -contains "MissingSetupFile")
   {
    write-host "MissingSetupFile"
    MissingSetupFile $Message;
   }

   elseif ($Category -contains "MissingFeature")
   {
    write-host "MissingFeature"
    MissingFeature $Message;
   }

    }

Wednesday, April 12, 2017

SharePoint 2016 - Zero-Downtime Patching - The biggest improvements

 

Disclaimer: this article only covers single aspects of the upgrade process. For a complete list of upgrade approaches including all details please check the following articles:

Patching SharePoint servers has always been a challenge. A major culprit for administrators is the fact that installing SharePoint fixes will cause downtime to the SharePoint farm. For SharePoint Server 2016 it was announced that we will have zero-downtime patching. This article intends to outline the reasons for downtimes with previous versions of SharePoint and the changes implemented in SharePoint Server 2016 to allow to perform zero-downtime patching including its constraints.

Historically this downtime can occur in two different steps:

  1. Installing the binaries
  2. Running the SharePoint configuration wizard.

Installing the binaries

While installing the actual binaries it is required to stop/restart SharePoint specific windows services and IIS websites to ensure that the updated files (e.g. dlls) are loaded.

The server specific downtime usually starts with running the hotfix executable till the hotfix installation is done.

With the huge hotfix files we are used to from SP2013 this can take several hours. Most of this time accounts for the extraction of the exe and cab file and then applying the various installer msp files which are included in the hotfix package.

Russ Maxwell has created a script which helps to significantly reduce the amount of time required to install the actual fixes but you will still experience a downtime on the specific server during the installation of the fix.

To overcome this issue we recommended to have high availability per role in your farm (at least two servers per role) to ensure that you can patch one server while the other one is online and continues to serve the requests. That means during patching you can remove one server from load balancing, patch it and add it back to load balancing. Then repeat the same steps for the other server(s).

While the patches are applied using this steps your farm will have servers with two different patch levels but that is fine as SharePoint will run in backward compatible mode if the database schema is older than the patch level of the servers in the farm.

So using redundant servers, you can achieve zero-downtime during the hotfix installation even with SharePoint 2013.

After the patch has been installed on all server you need to run the SharePoint configuration wizard.

Running the SharePoint configuration wizard

The SharePoint configuration wizard needs to be run on all machines in the farm to complete the hotfix installation.

You can use either the command line version (psconfig.exe) or the UI version (psconfigui.exe). I have discussed benefits and caveats of using the different methods in a separate article.

It is recommended to first run the configuration wizard on one of the app servers in the farm to perform the database upgrade. After this step is completed the configuration wizard can be started on all the other servers in the farm to perform the server specific upgrade operations (copy dlls, install features, apply security settings, …) on each of these servers (again you should remove the servers where psconfig is running from load balancing as services are restarted).

With SharePoint 2013 and before the database upgrade step will cause downtime on all servers in the farm as psconfig is updating databases which are used by all servers in the SharePoint farm. Depending on the specific updates applied to the database stored procedures, views, triggers and constraints could be dropped and recreated and other database content could be updated. SQL Queries issued by the SharePoint servers during this upgrade can fail if (e.g.) a stored procedure was called while the upgrade job was dropping it to replace it with an updated version or a fix contains (e.g.) two different changes to two different stored procedures where the changes depend on each other but only one stored proc was updated when the request comes in.

These limitations could also cause failed upgrades or excessive slowdowns in the upgrade process because of resource contention and locking. For these reasons accessing SharePoint content while the database is upgraded is unsupported and untested.

A partial workaround for this exists in SharePoint 2013 for updating the content database: After installing the patch and before running the SharePoint configuration wizard customers can run

Upgrade-SPContentDatabase -UseSnapshot …

Upgrade-SPContentDatabase can perform the same upgrade for a content database as the SharePoint configuration wizard. The benefit of using this Cmdlet is that you can run it in parallel in several powershell windows against different content databases. That can help to significantly reduce the database upgrade time after installing a hotfix as it allows to upgrade several content databases in parallel. The SharePoint configuration wizard would upgrade the content databases sequentially one after the other.

Another benefit is the -UseSnapshot parameter listed above.

This parameter will create a snapshot of the specified database and then perform all upgrade operations that apply to the database. Existing connections to the content database from the different SharePoint servers in the farm will be set to use the snapshot for the duration of the upgrade, and then switched back after successful completion of upgrade. Be aware that this parameter can only be used with versions of SQL Server that support creation and use of snapshots, for example, SQL Server Enterprise edition.

As all regular SharePoint operations are executed against the snapshot while the content database is upgraded the problems listed above will not occur. The caveat here is that the snapshot is read-only. That means although it prevents the above listed problems related to dropping stored procedures while they are in use they will prevent all write operations to the SQL database.

After upgrading the SharePoint content databases you still have to run the SharePoint configuration wizard to upgrade all the other SharePoint databases – and this can also cause downtime to services accessing these databases during the upgrade.

So it is not possible to achieve zero-downtime for read-write operations during the hotfix installation with SharePoint 2013.

 

Changes in SharePoint Server 2016

With SharePoint Server 2016 the amount of MSP files has been significantly reduced. This will ensure that the time to patch the servers will be much shorter. Aside of that you still have to ensure that you have more than one server per role (high availability) to guarantee zero-downtime patching as the windows services have to be restarted during patching. MinRole is not required for this! All the details on how to technically apply the patches can be found in the following Technet article:

The biggest improvements over SP2013 are on the upgrade side. Several improvements have been made to ensure that upgrading the SharePoint databases does not lead to a downtime for the end user. These changes include changes on how the changes are applied but also restricting what changes are allowed to be done in a hotfix request. E.g. all stored procedures have to be backward compatible to ensure that if one stored procedure is updated with a hotfix it can still be called from older stored procedures which are updated through a later step in the update cycle. We also update the stored procedures without dropping them to prevent outages if a stored proc is called while it is in the limbo state between drop and recreation.

These changes are long tested in SharePoint online where upgrades are performed for all SharePoint online servers every couple of weeks while the service is live without any read-only windows for customers.

These improvements apply as well to content databases and to other SharePoint databases that need to be upgraded. You can still use Upgrade-SPContentDatabase to speed up the database upgrade step but using the -SnapShot parameter will not bring a benefit when trying to minimize the downtime. It can actually be counter-productive as it leads to a read-only content database.

With the improvements implemented and using redundant servers for each role it is possible to achieve zero-downtime during the hotfix installation with SharePoint Server 2016.

Monday, April 3, 2017

Sharepoint - The feature with Id ‘GUID’ is referenced in the database ‘Content DB’ ,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

 

Solution

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

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