SharePoint Warmup Script

SharePoint Warmup Script

Update: Mittlerweile ist das SPBestWarmUp Skript von Jeff  in der Version 2.0.9 verfügbar. Dort wurden die nachfolgenden Probleme behoben. Direkt zum Download

Deshalb meine ganz klare Empfehlung, die neue Version einzusetzen. Danke Jeff Jones und Hagen Deike für die neue Version.

Die Meinungen zu dem Sinn und Nutzen von einem SharePoint Warmup Script gehen meines Wissens nach sehr weit auseinander. Von absolut nutzlos in SharePoint 2013 bis zur exzessiven Nutzung habe ich schon alles gesehen. Ich persönlich würde mich bei diesem Thema irgendwo in der Mitte einordnen. Ganz ohne SharePoint Warmup Script sinkt die Performance spürbar für den Nutzer und eine ausgiebige Nutzung verbessert die Performance nicht spürbar für den Benutzer. Wenn man in einer Suchmaschine nach einem Warmup Script für SharePoint sucht, findet man gefühlt eine unendliche Anzahl an verschiedenen Möglichkeiten. Bei genauer Betrachtung wird allerdings ein deutlicher Qualitätsunterschied hinsichtlich Stabilität und Funktionsumfang deutlich. Mein persönlicher Favorit ist hier das SharePoint Warmup Script von Jeff, das auf Codeplex verfügbar ist. Dieses SharePoint Warmup Script deckt eine große Funktionalität ab und ist universell für SharePoint 2010 und 2013 einsetzbar. Allerdings hat dieses SharePoint Warmup Script (Stand Version 1.6) auch ein paar Schwachstellen, auf die ich hier gerne hinweisen und mögliche Lösungen aufzeigen möchte.

Zeile 100: Ein ganz essentielles Problem ist, dass dieses SharePoint Warmup Script nur für Betriebssysteme kleiner gleich Windows Server 2008 R2 „sauber“ funktioniert. Ab Windows Server 2012 liegt der Internet Explorer die Temp Dateien an einer anderen Stelle im Dateisystem ab. Und dieses SharePoint Warmup Script nutzt zum Aufwärmen den Internet Explorer. Ohne Anpassung würde hier der freie Speicherplatz ziemlich schnell (je nach Nutzung) zur Neige gehen.

Zeile 149: Weiterhin nutzt das SharePoint Warmup Script zur Protokollierung die Transcript-Funktionalität von PowerShell. Dies ist eigentlich ziemlich nützlich um einen Verlauf zu haben und mögliche Fehler zu finden. Allerdings muss man sich bewusst sein, das auch hier die Logs standardmäßig im Dokumenten-Ordner des ausführenden Benutzers landen. Je nach Nutzung und Konfiguration kann hier ebenfalls eine beachtliche Datenmenge entstehen. Meiner Meinung nach sollten auf die Systempartition überhaupt keine Logs  landen, deshalb empfiehlt es sich den Pfad für die Logdateien auf eine andere Partition umzubiegen. Weiterhin kann weiterhin die Komprimierung für diesen Ordner aktiviert werden, was ebenfalls einiges an Speicherplatz spart.

Zeile 52: Der letzte Kritikpunkt ist die Installationsroutine für das SharePoint Warmup Script. Das Script bietet die Möglichkeit, es ganz bequem per Windows Aufgabenplanung automatisch ausführen zu lassen. Auf der einen Seite ist dies natürlich sehr hilfreich. Wer hat bei der Konfiguration der Aufgabe nicht erst einmal irgendwo nachgesehen, wie ein PowerShell Script darüber gestartet wird?! Allerdings sollte man nach der Installation die Zeitplanung der Aufgabe individuell anpassen. Weil nicht jede SharePoint Farm benötigt ein Script zum Aufwärmen, dass jede Stunde läuft. Sehr häufig steigt die Performance bereits , wenn man das SharePoint Warmup Script einmalig nach dem täglichen Recycling der Application Pools ausführt.

Eine entsprechend angepasste Version dieses SharePoint Warmup Skript könnte so aussehen:

<#  
.SYNOPSIS  
    Warm up SharePoint IIS memory cache by viewing pages from Internet Explorer
.DESCRIPTION  
    Loads the full page so resources like CSS, JS, and images are included.  Please modify lines 80-105
  to suit your portal content design (popular URLs, custom pages, etc.)

  Comments and suggestions always welcome!   or @spjeff
.PARAMETER install
  Typing "SPBestWarmUp.ps1 -install" will create a local Task Scheduler job under credentials of the
  current user.  Job runs every 60 minutes on the hour to help automatically populate cache after
  nightly IIS recycle.
.NOTES  
    File Name     : SPBestWarmUp.ps1
    Author        : Jeff Jones - @spjeff
    Version       : 1.6
  Last Modified : 11-21-2014
.LINK
  http://spbestwarmup.codeplex.com/
#>

param (
  [switch]$install
)

Function Installer() {
  # Add to Task Scheduler
  Write-Host "  Installing to Task Scheduler..." -ForegroundColor Green
  $user = $ENV:USERDOMAIN+"\"+$ENV:USERNAME
  Write-Host "  Current User: $user"
  
  # Attempt to detect password from IIS Pool (if current user is local admin and farm account)
  $appPools = Get-WmiObject -Namespace "root\MicrosoftIISV2" -Class "IIsApplicationPoolSetting" | Select WAMUserName, WAMUserPass
  foreach ($pool in $appPools) {			
    if ($pool.WAMUserName -like $user) {
      $pass = $pool.WAMUserPass
      if ($pass) {
        break
      }
    }
  }
  
  # Manual input if auto detect failed
  if (!$pass) {
    $pass = Read-Host "Enter password for $user "
  }
  
  # Create Task
  $cmd = """PowerShell.exe -ExecutionPolicy Bypass '$global:path'"""
  schtasks /create /tn "SPBestWarmUp" /ru $user /rp $pass /rl highest /sc daily /st 05:00 /tr $cmd
  Write-Host "  [OK]" -ForegroundColor Green
  Write-Host
}

Function WarmUp() {
  
  # Get URL list
  Add-PSSnapIn Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
  $was = Get-SPWebApplication -IncludeCentralAdministration
  
  # Warm up SharePoint web applications
  Write-Host "Opening Web Applications..."
  $global:ie = New-Object -Com "InternetExplorer.Application"
  $global:ie.Navigate("about:blank")
  $global:ie.Visible = $true
  $global:ieproc = (Get-Process -Name iexplore)|? {$_.MainWindowHandle -eq $global:ie.HWND}
  
  foreach ($wa in $was) {
    $url = $wa.Url
    IENavigateTo $url
    IENavigateTo $url"_layouts/viewlsts.aspx"
    IENavigateTo $url"_vti_bin/UserProfileService.asmx"
    IENavigateTo $url"_vti_bin/sts/spsecuritytokenservice.svc"
  }
  
  # Warm up Service Applications
  Get-SPServiceApplication |% {$_.EndPoints |% {$_.ListenUris |% {IENavigateTo $_.AbsoluteUri}}}
  
  # Warm up custom URLs
  Write-Host "Opening Custom URLs..."
  IENavigateTo "http://localhost:32843/Topology/topology.svc"
  
  # Warm up Host Name Site Collections (HNSC)
  Write-Host "Opening Host Name Site Collections (HNSC)..."
  $hnsc = Get-SPSite -Limit All |? {$_.HostHeaderIsSiteName -eq $true} | Select Url
  foreach ($sc in $hnsc) {
    IENavigateTo $sc.Url
  }
  
  # Close IE window
  if ($global:ie) {
    Write-Host "Closing IE"
    $global:ie.Quit()
  }
  $global:ieproc | Stop-Process -Force -ErrorAction SilentlyContinue
  
  # Clean Temporary Files
  Remove-item "$env:systemroot\system32\config\systemprofile\appdata\local\microsoft\Windows\temporary internet files\content.ie5\*.*" -Recurse -ErrorAction SilentlyContinue
  Remove-item "$env:systemroot\syswow64\config\systemprofile\appdata\local\microsoft\Windows\temporary internet files\content.ie5\*.*" -Recurse -ErrorAction SilentlyContinue
  Remove-item "$env:systemroot\system32\config\systemprofile\AppData\Local\Microsoft\Windows\INetCache\IE\*.*" -Recurse -ErrorAction SilentlyContinue
}

Function IENavigateTo([string] $url, [int] $delayTime = 500) {
  # Navigate to a given URL
  if ($url) {
    if ($url.ToUpper().StartsWith("HTTP")) {
      Write-Host "  Navigating to $url"
      try {
        $global:ie.Navigate($url)
      } catch {
        try {
          $pid = $global:ieproc.id
        } catch {}
        Write-Host "  IE not responding.  Closing process ID $pid"
        $global:ie.Quit()
        $global:ieproc | Stop-Process -Force -ErrorAction SilentlyContinue
        $global:ie = New-Object -Com "InternetExplorer.Application"
        $global:ie.Navigate("about:blank")
        $global:ie.Visible = $true
        $global:ieproc = (Get-Process -Name iexplore)|? {$_.MainWindowHandle -eq $global:ie.HWND}
      }
      IEWaitForPage $delayTime
    }
  }
}

Function IEWaitForPage([int] $delayTime = 500) {
  # Wait for current page to finish loading
  $loaded = $false
  $loop = 0
  $maxLoop = 20
  while ($loaded -eq $false) {
    $loop++
    if ($loop -gt $maxLoop) {
      $loaded = $true
    }
    [System.Threading.Thread]::Sleep($delayTime) 
    # If the browser is not busy, the page is loaded
    if (-not $global:ie.Busy)
    {
      $loaded = $true
    }
  }
}

#Main
$transcriptfile = "D:\SP\WarmUp\"+"SPWarmUp"+"."+(get-date -format yyyyMMddhhmmss)+".log"
write-host "Transcript to:$transcriptfile"
Start-Transcript -append -path $transcriptfile
Write-Host "SPBestWarmUp v1.6  (last updated 11-21-2014)`n"

#Check Permission Level
If (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(`
    [Security.Principal.WindowsBuiltInRole] "Administrator"))
{
    Write-Warning "You do not have Administrator rights to run this script!`nPlease re-run this script as an Administrator!"
    break
} else {
    #Warm up
    $global:path = $MyInvocation.MyCommand.Path
    $tasks = schtasks /query /fo csv | ConvertFrom-Csv
    $spb = $tasks |? {$_.TaskName -eq "\SPBestWarmUp"}
    if (!$spb -and !$install) {
      Write-Host "Tip: to install on Task Scheduler run the command ""SPBestWarmUp.ps1 -install""" -ForegroundColor Yellow
    }
    if ($install) {
      Installer
    }
    WarmUp
}
Stop-Transcript

Wie schon gesagt ist dieses SharePoint Warmup Script initial nicht von mir, sondern von Codeplex. Ich habe nur ein paar Schwachstellen davon verbessert, die in der Praxis aus meiner Sicht ungünstig bzw. fehlerhaft sind.

Wenn ihr noch andere Probleme findet, würde ich mich über euer Feedback freuen.

Ansonsten geschieht der Einsatz von diesem SharePoint Warmup Script natürlich auf eure eigene Gefahr. 🙂

Happy SharePointing…

Schreibe einen Kommentar