How to warm-up SharePoint or other web applications and WCF (SOAP) services with PowerShell

There are many reasons you might want to warm-up a web application occasionally. It can be after a fresh deployment or on a regular basis after recycling application pools. Some times you might also need to warm-up SOAP services without going through front-end.

It might seems to be any easy task specially if you have PowerShell 3.0 or higher on your servers, but after Googling a while and reviewing some of the top hits I discovered that each solution is missing a part. Some only work in a single server scenario and some has forgotten that each HTTP response might contain links to scripts and images that we need to download and finally I could not find anything for SOAP services that just works. Long story short I decided to put together a simple script that just works and is easy to change to everyone’s needs.

Please note that my only assumption is you have PowerShell 3.0+ in your servers.

Currently the script takes care of the following tasks, but I will most likely improve it to cover other useful scenarios.

  • Calling SOAP operations and sending parameters and custom headers
  • Calling front-end URIs and downloading scripts and images that are local to the front-end
  • Logging to a configurable folder and file name
  • Cleaning up old log files

Currently, I have the following points in mind to improve the script.

  • Put configuration in a different file.
  • Improve function definitions (named and typed parameters and description).
  • Default values for parameters when it makes sense (e.g. log folder can be the current folder).
  • Support REST services.

I’m open to any suggestion and feature request. Please let me know if you found it useful or if have got something wrong.

How to warm-up SharePoint or other web applications and WCF (SOAP) services with PowerShell

Per developer web.config files using out-of-the-box Visual Studio functionality

It might be a repetitive subject and some might argue that it’s even best to have identical web.config files for all developer. But, the fact it sometimes it’s inevitable! you are not always building software from scratch. It might be an extension to a huge software that contains per-machine keys and configurations. Unfortunately there are many blog posts here and there that suggest using batch files and methods that are more like a hack. Here I’m going to explain how to use the out-of-the-box functionality in Visual Studio without any external tool or hack.

If you already know how those two web.debug.config and web.release.config files work you’ll get the idea. Basically they are a kind of Xslt transformation that are selected based on the current configuration (web.($configuration).config) and we want the same thing but based on current username (web.($Username).config). To learn how to use web.config transformations and its syntax visit “http://go.microsoft.com/fwlink/?LinkId=125889

And here is the recipe:

  1. Right-click over the project name in Solution Explorer and select “Add \ New Item…”
  2. Select XML File under Data category and give it a name in the following pattern web.{username}.config (e.g. web.reza.config).
  3. Copy-paste the content of web.debug.config to this new file (i.e. web.{username}.config) to use as a starting point and override the settings as you need. If you don’t feel comfortable with the transformation syntax, take a look at this page. It’s fairly easy.

Here is an example to override the <machineKey> attributes.

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <system.web>
    <machineKey xdt:Transform="SetAttributes" validationKey="EFEF01678000A361AADF4E01DB5AD356C91111E781660310" decryptionKey="6EF12ECA1A36ACAC4D08212E9FA8F34B1919A3DD818B8E0F" validation="SHA1" />
</configuration>
  1. Save the file.
  2. Right-click over the project name in Solution Explorer and select Unload Project.
  3. Right-click again over the project name and this time select Edit {projectfilename}.
  4. At the end of the file, right before </Project>, paste the following piece of XML (don’t worry I will explain later).
<Target Name="AfterBuild" Condition="Exists('web.$(USERNAME).config')">
    <Copy SourceFiles="web.config" DestinationFiles="obj\$(Configuration)\tempweb.config" />
    <TransformXml Source="obj\$(Configuration)\tempweb.config" Transform="web.$(USERNAME).config" Destination="obj\$(Configuration)\tempweb2.config" />
    <ReadLinesFromFile File="obj\$(Configuration)\tempweb2.config">
      <Output TaskParameter="Lines" ItemName="TransformedWebConfig" />
    </ReadLinesFromFile>
    <ReadLinesFromFile File="web.config">
      <Output TaskParameter="Lines" ItemName="UnTransformedWebConfig" />
    </ReadLinesFromFile>
    <Copy Condition=" @(UnTransformedWebConfig) != @(TransformedWebConfig) " SourceFiles="obj\$(Configuration)\tempweb2.config" DestinationFiles="web.config" OverwriteReadOnlyFiles="True" />
  </Target>
  1. Save the project file.
  2. Right-click on the project file again and select Reload Project this time.
  3. Build and project and check the result.

And now the explanation. Basically what we did was to add an AfterBuild process (you can also use a BeforeBuild) and set a condition for it to only run when there is web.{username}.config file in the project’s root. It means that if there is no such file for the current developer, it will be skipped. Within the process we have 5 actions that run in the order that is written:

  • <Copy> makes a copy of web.config file to “obj\($configuration)” folder with the name “tempweb.config”. The value of $Configuration depends on the build configuration currently selected in your Visual Studio (e.g. Release or Debug).
  • <TransformXml> runs the transformation to override developer specific values in the tempweb.config file and generates another file (tempweb2.config).
  • The two <ReadLinesFromFile> actions load the content of tempweb2.config and original web.config file into two different variables.
  • The last <Copy> replaces the original web.config only if there is any difference between the generated file and the original (Condition="@(UnTransformedWebConfig) != @(TransformedWebConfig)").
Per developer web.config files using out-of-the-box Visual Studio functionality