After server patching you might find that the Reporting Services service will fail to start; not just SQL 2005 but others too. This is described in a Microsoft knowledge base article. The problem is that applying those instructions is a manual and error prone process.

Methods 3 and 4 from the article are the best. I also used Method 2 in previous revisions of this article but it proved less effective. If you want to give it a go I recorded which registry keys the Group Policy tool changes and recorded them below.

I've written the below PowerShell script to automate the process:

  • Set the ServicesPipeTimeout (unless it's set equal to or greater than what we were going to). This will fix SSRS after the next reboot.
  • Set the recommended registry key, temporarily, then change it back after SSRS has started.

I've used this fairly extensively in production. My registry path creation / removal process is a little dodgy.

# https://support.microsoft.com/en-us/kb/2745448
# You cannot start SQL Server Reporting Services after you apply the update that is discussed in KB 2677070

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"

# Method 4: Increase the default service timeout.
# This requires a restart, but is a long-term solution.
#
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Control"
try {
    $original = Get-ItemProperty $regPath -Name ServicesPipeTimeout
    if ($original.ServicesPipeTimeout -lt 60000) { 
        Write-Verbose "Overwriting $regpath\ServicesPipeTimeout value from $($original.ServicesPipeTimeout)"
        Set-ItemProperty $regPath -Name "ServicesPipeTimeout" -Type DWord -Value 60000
    } else {
        Write-Warning "Keeping $regpath\ServicesPipeTimeout value at $($original.ServicesPipeTimeout)"
    }
} catch {
    Write-Host "Setting ServicesPipeTimeout"
    Set-ItemProperty $regPath -Name "ServicesPipeTimeout" -Type DWord -Value 60000
}

# Method 3: Modify the registry.
# This doesn't require a restart, and it seems to be the most reliable.

$regPath = "HKLM:\Software\Policies\Microsoft\SystemCertificates\AuthRoot"
$regKey = "DisableRootAutoUpdate"
$removePath = $false
$removeKey = $false

# Create the registry key if it doesn't exist, and mark to remove it later
if (!(Test-Path $regPath)) {
    Write-Verbose "Creating $regPath"
    New-Item $regPath | Out-Null
    $removePath = $true
}

# Save the original property value if possible, otherwise mark to remove it later
try {
    $original = Get-ItemProperty $regPath -Name $regKey -ErrorAction:Stop
    Write-Verbose "Saved original value"
} catch {
    $removeKey = $true
}

# Update or create the property value
Set-ItemProperty $regPath -Name $regKey -Type DWord -Value 1 | Out-Null

$services = Get-Service -Name "ReportServer*" | Where-Object { $_.Status -ne "Running" }
foreach ($service in $services) {
    Write-Verbose "Starting $($service.DisplayName)"
    $service.Start()
}

# Remove or restore the property value
if ($removeKey) {
    Write-Verbose "Removing key"
    Remove-ItemProperty -Path $regPath -Name $regKey
} else {
    Write-Verbose "Restoring original value"
    Set-ItemProperty $regPath -Name $regKey -Type DWord -Value $original.DisableRootAutoUpdate
}

# Remove the registry key if we created it
if ($removePath) {
    Write-Verbose "Removing path"
    Remove-Item $regPath
}

<#
# Method 2: Change the Group Policy settings.
# This doesn't require a restart.
#
# Local Policy, Computer Configuration, Windows Settings, Security Settings, Public Key Policies,
# Certificate Path Validation Settings, Network Retrieval
# - Enable "Define these policy settings"
# - Disable "Automatically update certificates in the Microsoft Root Certificate Program (recommend)"
#
# Note: There's a detailed write-up of this key here:
# http://blogs.technet.com/b/instan/archive/2013/06/13/adcs-and-dedicated-crl-signing-certificates.aspx
#
$regPath = "HKLM:\SOFTWARE\Policies\Microsoft\SystemCertificates\ChainEngine\Config"
$removePath = $false
$removeKey = $false

# Create the registry key if it doesn't exist, and mark to remove it later
if (!(Test-Path $regPath)) {
    Write-Verbose "Creating $regPath"
    New-Item $regPath
    $removePath = $true
}

# Save the original property value if possible, otherwise mark to remove it later
try {
    $original = Get-ItemProperty HKLM:\SOFTWARE\Policies\Microsoft\SystemCertificates\ChainEngine\Config -Name Options -ErrorAction:Stop
    Write-Verbose "Saved original value"
} catch {
    $removeKey = $true
}

# Update or create the property value
Set-ItemProperty $regPath -Name Options -Type DWord -Value 2 | Out-Null

$services = Get-Service -Name "ReportServer*" | Where-Object { $_.Status -ne "Running" }
foreach ($service in $services) {
    Write-Verbose "Starting $($service.DisplayName)"
    $service.Start()
}

# Remove or restore the property value
if ($removeKey) {
    Write-Verbose "Removing key"
    Remove-ItemProperty -Path $regPath -Name Options
} else {
    Write-Verbose "Restoring original value"
    Set-ItemProperty HKLM:\SOFTWARE\Policies\Microsoft\SystemCertificates\ChainEngine\Config -Name Options -Type DWord -Value $original.Options
}

# Remove the registry key if we created it
if ($removePath) {
    Write-Verbose "Removing path"
    Remove-Item $regPath
}

#>

foreach ($i in 1..30) {
    $failed = $services | Get-Service | Where-Object { $_.Status -ne "Running" } | Select -ExpandProperty DisplayName

    if (!$failed) {
        break
    }

    Start-Sleep -Seconds 1
}

if ($failed) {
    Write-Error "Failed to start $failed."
} else {
    Write-Host "Success!"
}