QueryFeatures issue when performing a feature upgrade

Awhile ago I had to upgrade a SharePoint solution for a customer. Everything was tested thoroughly and it all worked on my machine. Full of confidence I went to the customer and we executed my PowerShell script to update the solution. And guess what? An error occurred. In this article I want to show you (relevant part of) my PowerShell script how I did the upgrade. what error occurred, why and how I solved it.

The Script

When updating a solution there is no need to retract and re-install the solution and in stead you should use the Update-SPSolution cmdlet. This way feature upgrade actions and/or events are activated. If you have new features, you will have to manually install them.

param( [string]$url="http://intranet.ochadev.local" )

$deployConfig = Get-Content Solutions.xml

foreach( $solution in $deployConfig.Solutions.Solution )
{
    if( $solution.deploy.ToUpper().Equals("TRUE") )
    {
        .solution.ps1 -solution $solution.file -deploy -url $url 
    }

    if( $solution.update.ToUpper().Equals("TRUE") )
    {
        .solution.ps1 -solution $solution.file -update -url $url 
    }

}

Write-Host -ForegroundColor Yellow "Restarting the SharePoint Timer Service..." -NoNewline
Restart-Service SPTimerV4
sleep -Seconds 8
Write-Host -ForegroundColor Green " DONE"

# Install new features
Install-SPFeature -Path Customer.SharePoint.Intranet.Feature1
Install-SPFeature -Path Customer.SharePoint.Intranet.Feature2

# Enable feature 1
Write-Host -ForegroundColor Yellow "Activating feature 1" -NoNewline
Enable-SPFeature -id f2d467b7-bbf3-4c56-8b99-919ea06121c0 -url $url -Confirm:$false
Write-Host -ForegroundColor Green " DONE"

# Enable feature 2
Write-Host -ForegroundColor Yellow "Activating feature 2" -NoNewline
Enable-SPFeature -id da0a0018-2a8a-43be-9c10-fa47317939b1 -url $url -Confirm:$false
Write-Host -ForegroundColor Green " DONE"

# Update current features
$site = Get-SPSite $url

$featuresToUpgrade = $site.QueryFeatures("Site", $true)
foreach ($f in $featuresToUpgrade)
{
    Write-Host -ForegroundColor Yellow "Upgrading feature " $f.Definition.DisplayName -NoNewline
    $f.Upgrade( $false )
    Write-Host -ForegroundColor Green " DONE"
    
}

$featuresToUpgrade = $site.QueryFeatures("Web", $true)
foreach ($f in $featuresToUpgrade)
{
    Write-Host -ForegroundColor Yellow "Upgrading feature " $f.Definition.DisplayName -NoNewline
    $f.Upgrade( $false )
    Write-Host -ForegroundColor Green " DONE"
    
}

Write-Host -ForegroundColor Green "Finished upgrading"

The script starts with deploy new solutions and updating existing ones. This list of solutions is stored in a XML configuration file. After that the script installs and activates new features. And last but not least it updates any feature that needs to be updated. To know what features need to be updated, the method QueryFeatures is used.

The Error

When the line

$featuresToUpgrade = $site.QueryFeatures("Web", $true)

is executed the following error occurred:

An error occurred while enumerating through a collection: Unable to access web scoped feature (Id: 00bfea71-d1ce-42de-9c63-a44004ce0104) because it references   a non-existent or broken web (Id: e8a747cc-2cf4-49fe-8b20-ea44d6fae62b) on site ‘http://intranet.ochadev.local’.

Exception: System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

   at Microsoft.SharePoint.Library.SPRequest.GetAllWebsOfSite(String bstrUrl, Object& pvarWebs, Object& pvarWebIds, Object& pvarParentWebs, Object& pvarLangs, Object& pvarTitles, Object& pvarUIVersions, Object& pvarFlags, Object& pvarWebTemplates, Object& pvarConfigurations, Object& pvarMasterUrls, Object& pvarCustomMasterUrls)

   at Microsoft.SharePoint.SPSite.SPWebCollectionProvider.GetWebsData(String[]& strNames, String[]& strServiceRelUrls, Guid[]& guidWebIds, Int32[]& nLanguages, String[]& strTitles, String[]& strDescriptions, String[]& strCreationTimes, String[]& strModifiedTimes, Boolean[]& bUserIsWebAdmins, Int32[]& nWebTemplates, Int16[]& nProvisionConfigs, Int16[]& nMeetingCounts, Int32[]& nUIVersions, Int32[]& nFlags, String[]& strMasterUrls, String[]& strCustomMasterUrls)

   at Microsoft.SharePoint.SPWebCollection.EnsureWebsData()

   at Microsoft.SharePoint.SPWebCollection.get_Item(Guid id)

   at Microsoft.SharePoint.SPFeatureEnumeratorBase.GetCachedWeb(SPSite site, Guid webId, Guid featureId).

Hmm. Did I missed something? I was logged on the server as a farm administrator (it was DOMAINAdministrator. Not really a best practice, but sadly that was the case), started PowerShell as an Administrator. All okay, don’t you think?

The Solution

Access denied. It got me thinking. Why do I have an Access Denied exception? I am a farm administrator. But, that does mean I have explicit access to a site or web. Was this user account somehow logged in the site before? Let’s take a look. And yes, there it was:

image

The (Farm) Administrator account had logged in the site some day and then it got very little permissions set explicitly. I removed this permission for the Administrator account and tried my script again. It worked like a charm now!

Share