Multiple front-end aware warmup script for SharePoint

Below is a script which retrieves all site collection urls, and all front end servers in the local SharePoint farm, and the “gets” every url from every front end server, bypassing the load balancer device by using the front end server as a “proxy server” for the .Net webrequest.  This script can be used to “warm up” all sites after a scheduled recycle of the IIS application pools.

The script can be run on any server in the farm (front end or application), as long as the SharePoint object model is available (so obviously not on the SQL server).  The script takes no parameters.  Feedback is appreciated. Enjoy.


################################################################################
# Name           : Initialize-SharePointSiteCollections.ps1
# Version        : 1.4
# Date           : 15/09/2009
# Author         : Bert Van Landeghem
# Description    : performs an HTTP GET against the url of the rootweb of each 
#                   site collection in the local farm to force JIT to happen. This 
#                  version is compatible with multi-server farm. It bypasses the 
#                   load balancer by using the front end server names as proxy 
#                    servers for the WebRequest.
# Dependencies   : Assembly Microsoft.SharePoint
################################################################################

param()

#region Functions

    function Get-SiteCollectionUrl{

        ############################################################################
        # Name    : Get-SiteCollectionUrl
        # Usage    : returns url's of root sites of all site collections in the farm.
        # Author: Bert Van Landeghem, 15/09/2009
        ############################################################################

        [Void][System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")

        [Microsoft.SharePoint.Administration.SPWebService]::ContentService `
            | foreach-object{$_.WebApplications} `
            | foreach-object{$_.Sites} `
            | foreach-object{$_.url}

    }

    function Get-FarmFrontEndServer{

        ############################################################################
        # Name    : Get-FarmFrontEndServer
        # Usage    : returns all web front end servers in the farm.
        # Author: Bert Van Landeghem, 15/09/2009
        ############################################################################

        [Void][System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")

        [Microsoft.SharePoint.Administration.SPFarm]::Local`
            | %{ $_.Services} `
            | ?{$_.typename -eq "Windows SharePoint Services Web Application"}`
            | %{$_.instances} `
            | %{$_.Server} `
            | %{$_.Address}

    }

    Function Get-HTTPResponse{

        ############################################################################
        # Name    : Get-HTTPResponse
        # Type    : pipeline, expects incoming string objects containing url's 
        #          existing in the local SharePoint farm (see Get-SiteCollectionUrl).
        # Usage    : connects to the specified url, directing the request to every web 
        #          front end in the farm, bypassing the load balancer device by 
        #          using the front end's name as a web proxy.
        # Author: Bert Van Landeghem, 15/09/2009
        ############################################################################

        PARAM(
        )

        BEGIN{
            $FarmFrontEndServers = Get-FarmFrontEndServer
            write-debug $FarmFrontEndServers
        }
        PROCESS{
            trap [System.Net.WebException] {
                write-debug "$($_.Exception.Status) while retrieving $($WebRequest.RequestUri) on server $server : $($_.Exception.Message)"
                $result                    = "" | Select-Object Url, Server, Status
                $result.server             = $server
                $result.status             = "$($_.Exception.Message)"
                $result.url                = $WebRequest.RequestUri
                Write-Output $result
                continue;
            }

            write-debug "Opening url $_ ."

            # following yields http:// or https:// depending on incoming url
            $uriScheme                     = ([System.Uri] $_).Scheme + [Uri]::SchemeDelimiter

            foreach($server in $FarmFrontEndServers)
            {
                write-debug "Contacting server $server."

                $ByPassOnLocal            = $false
                $ProxyUri                 = $uriScheme + $server
                $Proxy                    = New-Object system.Net.WebProxy($ProxyUri, $ByPassOnLocal)
                $WebRequest               = [System.Net.HttpWebRequest]::Create( $_ )
                $WebRequest.UseDefaultCredentials     = $true
                $WebRequest.UserAgent     = "SharePoint_Warm-up_Script"
                $WebRequest.CachePolicy   = [System.Net.Cache.RequestCacheLevel]::CacheIfAvailable
                $WebRequest.Proxy         = $Proxy
                $WebRequest.Timeout       = 300000
                $WebResponse              = $WebRequest.GetResponse()

                If ($WebResponse)
                {
                    write-debug "$server: $($WebResponse.ResponseUri) OK"
                    $result               = "" | Select-Object Url, Server, Status
                    $result.url           = $WebRequest.RequestUri
                    $result.server        = $server
                    $result.status        = "OK"
                    $WebResponse.Close()

                    Write-Output $result

                }
            }
        }
        END{}

    }
#endregion functions

#region Main Procedure

    Get-SiteCollectionUrl `
        | Get-HTTPResponse `
        | sort-object url,server `
        | ft -AutoSize -Wrap

#endregion 



		
Advertisements

13 thoughts on “Multiple front-end aware warmup script for SharePoint

  1. Create post, this was exactly what I was searching for: A warmup script that can handle load balanced environments without modifing the hosts file. Using the frontend server address as proxy is a create trick. It also works with SharePoint 2010. Awesome!

  2. I am having a problem getting this working in SharePoint 2010. We are using network load balancing. I get an error in line 89. which is $Proxy=New-Object system.Net.WebProxy($ProxyUri, $ByPassOnLocal). Error is New-Object : Exception calling “.ctor” with “2” argument(s): “Invalid URI: The hostname could not be parsed.”

    Any ideas?

      • I found what the problem was. It was that the Function Get-FarmFrontEndServer had some problems. In the first part the [Void][System.Reflection.Assembly]::Load(“Microsoft.SharePoint, Version=12.0.0.0… Should be loading 14 for SharePoint 2010 and also in the …?{$_.typename -eq “Microsoft SharePoint… should be looking for Microsoft SharePoint Foundation Web Application.

        Still have some problems but am getting there. Problem I am getting now is “Proxy”: “The ServicePointManager does not support proxies with the https scheme.”

  3. I found what the problem was. It was that the Function Get-FarmFrontEndServer had some problems. In the first part the [Void][System.Reflection.Assembly]::Load(“Microsoft.SharePoint, Version=12.0.0.0… Should be loading 14 for SharePoint 2010 and also in the …?{$_.typename -eq “Microsoft SharePoint… should be looking for Microsoft SharePoint Foundation Web Application.

    Still have some problems but am getting there. Problem I am getting now is “Proxy”: “The ServicePointManager does not support proxies with the https scheme.”

    • Hi Tom,
      I am also facing the similar issue like “The ServicePointManager does not support proxies with the https scheme.” Please let me know if you have found a way to overcome this.

      Thanks
      kesav

    • Hi Tom,
      I am facing the same problem as you with “Proxy”: “The ServicePointManager does not support proxies with the https scheme.”
      Did you find a workaround on this topic? Thanks for giving feed-back if you have found something interesting on this.
      Regards,
      Thanh-Nu

  4. Hi Bert,
    I have been looking for a warmup script that would work for all WFEs, and your script just matches this requirement. I have however a question: In other warmup scripts like the one by Kirk Hofer, he mentioned that using WebRequest object to hit the site does NOT warm up the site, and you actually need to get content from the page by:
    $wc = new-object net.webclient
    …..
    $s = $wc.DownloadString($web.Url)

    Comparing with your script, (using $WebRequest.GetResponse()) what is your opinion about this?
    Thank you in advance for your advice.
    Regards,
    Thanh-Nu

    • Hi Thanh-Nu,
      it’s been a while since I’ve worked on the script. I’ll try to find out more in the next few days.
      Regards,
      Bert.

      • Hi Thanh-Nu,
        I’ve just tried, and both seem to work identically… The webclient also has a proxy property, so you can easily rewrite the script to use that method if you prefer, the logic stays the same.

        Regards,
        Bert.

  5. Hi Bert,
    Thank you very much for your reply. I have been fighting with the https problem. When I have https, I cannot bypass the NLB, because if I set the Proxy, I will get: “The ServicePointManager does not support proxies with the https scheme.”
    I am wondering if i can extende the Web Application with http URL, and use the Warmup script with the http URL instead. Since all URLs in AAM would point to the same Web Application, the fact that I warmup the “alias” URL with http would rebuild the cache or am I wrong? Do you know if the cache is built with the URLs and protocole (https)? In this case, we shoudl Warmup all URLs that are defined in AAM?
    Thank you in advance for your help.
    Thanh-Nu

  6. Does this work for 2013. I changed version to 15.0.0.0 but keen on getting error line 93 char 34 $server: $($WebResponse.ResponseUri) OK variable refrence is not valid. ‘:’ is not followed by a valid variable name character.

    • Hi. Sorry, I don’t know if this works for 2013. I’ve only worked with Sharepoint version 2007 and have since then moved to SQL Server.

      If another reader could perhaps shed a light on this, that would be most helpfull.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s