MSDeploy , XPath and XSL: Part III: Auto generate setParamFile from package and batch file to migrate apps to sites

MSdeploy along with XSL is the way to go if you want to simplify many of the routine tasks that one needs to do. Two of the common scenarios are listed below. Before we start, you can download msxsl for free from here and the web deployment tool (msdeploy) RTW from here (x86 / x64 )

Auto generate set parameters XML file from a package:

If you have a package that you are trying to deploy to multiple servers and have different values to be specified for the params based on the servers (such as staging, server, production etc) then setParamFile is the switch you use to specify the file which has the values for the params defined in the package. The command is given below.

msdeploy -verb:sync -source:package="c:\packages\mypackage.zip" -dest:auto,computername=StagingServer1 -setParamFile="c:\StagingParameters.xml"

To create this xml file which defines the values for the parameters you can either type it manually or use the following one liner to generate it for you. Once you have this file, all you need to do is find the params that do not have a default value and specify the value and modify the defaultvalues that you expect to be different. You can download the xsl file from here (As earlier rename the file to .xsl before using it)

msdeploy -verb:getParameters -source:package=e:\wp\wordpress.zip -xml | c:\xsl\msxsl.exe - c:\xsl\setparamgen.xsl -o setParameters.xml

This xsl file is pasted below:

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

  <xsl:template match ="/" >         
        <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="parameters" >

    <parameters>
<xsl:for-each select="parameter" >
<xsl:if test="not(contains(@tags,'Hidden')) and not(@defaultValue)">
   <xsl:element name="setParameter" >
   <xsl:attribute name="name" >
   <xsl:value-of select="@name" />
   </xsl:attribute>
   <xsl:attribute name="value" >
   <xsl:value-of select="@defaultValue" />
   </xsl:attribute>
   </xsl:element>
</xsl:if>
</xsl:for-each>
</parameters>

  </xsl:template >
</xsl:stylesheet >

Migrating applications (vDirs) under a site on IIS6 to discreet sites on IIS7:

A typical scenario is a user having bunch of applications under a site on IIS6. When planning to migrate to IIS7 users want to convert these applications to discreet sites on IIS7. With msdeploy RTW you can do this as one single step as given below:

msdeploy.exe -verb:sync -presync:runCommand="md D:\inetpub\wwwroot\NewContent & D:\Windows\System32\inetsrv\appcmd add site /name:NewSite /id:21 /bindings:http/*:8082: /physicalPath:D:\inetpub\wwwroot\NewContent " -source:metakey=/LM/W3SVC/1/Root/myapp -dest:metakey=/lm/w3svc/21/root,computername=iis7server,tempAgent=true

The above command uses:

  • preSync feature of msdeploy with runCommand to
    • Create an empty directory on the target server
    • Create a site on the target server that points to this directory for content
  • metaKey provider to sync the application on source to this newly created site on the target

This works and does the job. The issue with this command is that

  • Its not easy to understand
  • What if you have 30 applications that you need to convert to sites on the target.

Again we have xsl to our rescue. Here’s a one liner again that will give you the batch file that you need. All you need to do is execute the batch file and there you have 50 of your apps migrated as sites on the target iis7 server. You can download the xsl from here (As earlier rename the file to .xsl before using it). The xsl file has variables defined at the top if you want to use any value other than that I have used in this example.

msdeploy.exe -verb:dump -source:metakey=/lm/w3svc/1 -xml -disableLink:Content -xpath="//*[@name='AppRoot' and @value!='/LM/W3SVC/1/ROOT']" | msxsl.exe - batchfilegen.xsl -o convertappstosites.cmd

This will generate the convertapptosites.cmd which can be used to migrate apps to sites on the target. I also would like to explain that the above command is getting all the apps that are under the site with the ID 1. You can remove the trailing /1 from the source metakey to get all apps beneath all sites on the source.

The xsl file for this is given below:

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text" encoding="US-ASCII" />

<!-- Change the server name, base binding info and the root content path of the target server to suit your needs -->
   <xsl:variable name="s" select="'abcdefghijklmnopqrstuvwxyz'" />
   <xsl:variable name="u" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />
   <xsl:variable name="compname" select="'myserver'" />
   <xsl:variable name="serverbinding" select="'8081'" />
   <xsl:variable name="RootContentDir" select="'D:\inetpub\wwwroot\'" />

  <xsl:template match ="/" >         
        <xsl:apply-templates />
  </xsl:template>

<xsl:template match="output" >   
      <xsl:for-each select="metaProperty" >
<xsl:variable name="sitename" select="substring-after(substring-after(translate(@value,$s,$u),'ROOT'),'/')" />               
<xsl:text>MSDeploy.exe -verb:sync -presync:runCommand="md </xsl:text>
<xsl:value-of select="$RootContentDir" />
<xsl:value-of select=" $sitename" />
<xsl:text > &amp; D:\Windows\System32\inetsrv\appcmd add site /name:</xsl:text>
<xsl:value-of select="$sitename" />

<!-- it uses 20 as the increment to get a new metakey for the target site. You can change it to any value based on your target server -->
<xsl:text> /id:</xsl:text><xsl:value-of select="position()+20" /><xsl:text> /bindings:http/*:</xsl:text>
<xsl:value-of select="position() + $serverbinding" />
<xsl:text>: /physicalPath:</xsl:text>
<xsl:value-of select="$RootContentDir" />
<xsl:value-of select=" $sitename" />
<xsl:text> " -source:metakey=</xsl:text>
<xsl:value-of select="@value" />
<xsl:text> -dest:metakey=/lm/w3svc/</xsl:text>
<xsl:value-of select="position()+20" />
<xsl:text>/root,computername=</xsl:text><xsl:value-of select="$compname" /><xsl:text>,tempAgent=true -verbose
</xsl:text>
      </xsl:for-each>
  </xsl:template >
</xsl:stylesheet >

Happy deploying.

3 Comments

  • Thanks! Have been trying to find out whether or not this kind of thing was actually possible - couldn't find the -setParamFile switch documented on MSDN/Technet!

    Now it's time to try and figure out how you can maintain the file timestamps from staging to deployment; my static file ETags are not in sync across my webfarm!

  • There's a typo in the XSL in the first half of the post - instead of <xsl:element name="setParameters" it should be <xsl:element name="setParameter" - tried to use a model xml generated by hand from your xsl but kept getting an unexpected element error.

    Had to reflect the current version of msdeploy to find out that it's expecting a 'setParameter' node for each parameter.

    For anyone who wants to know the actual format for this file it's




  • I have fixed the typo in the blog post and in the XSL. Thanks LordZoltan, for pointing it out.

Comments have been disabled for this content.