MSDeploy Custom Provider to execute batch files

Posted: Jun 19, 2009  2 comments  

Average Rating

Tags

Overview

The IIS Web Deployment Tool (also known as MSDeploy) simplifies the migration, management and deployment of IIS Web servers, Web applications and Web sites. MSDeploy also offers the ability to run custom providers. These providers unlock hidden power in MSDeploy.

In this article you will find a sample code for a custom MSDeploy provider that executes batch file commands as a part of MSDeploy sync. The batch file provider can be used to execute custom scripts before or after deployment to make the deployment process a seamless one. You can set up performance counters for a particular MSDeploy sync, make a batch file to copy content with xcopy rather than with MSDeploy (but remember that we’re faster than xcopy!) to name just a few possibilities. The code in this article is meant as a sample to get you started on writing your own custom MSDeploy provider, so that you do not have to wait for the MSDeploy RTW release (Rumor has it that the MSDeploy team is going to have a batch file provider in RTW release). In any case, the code is built thankfully to a great sample and blog that Yamini Jagadeesan wrote a couple of months ago on MSDeploy MySql custom provider that lets you sync from one MySql database to another. If you haven’t familiarized yourself with the article, it is a great read and another good start-up solution for MSDeploy custom provider.

Needed for this Walkthrough

To walk through installation of the provider, you might need to download gacutil to add the assembly to the GAC. You can get gacutil as a part of .NET Framework SDK or download it separately.

Download and Install

First, download the zip file with the project. Solution contains the following files:

  • BatchProviderFactory.cs – an entry point to your provider that kindly returns an instance of the provider in overridden CreateProvider method.
  • BatchProvider.cs – the provider itself that initiates execution of a batch file.
  • Strongname.pfx – the file with a key to sign the assembly for strong name verification. The password is “MSDeployRocks”, but you can delete the pfx file and specify your own key and password for singing the assembly by going to Project Properties-->Signing in Visual Studio.

To install the provider you need to

  1. Compile the project (or just use this dll)
  2. Add the new assembly to the GAC by executing

    gacutil /if BatchProvider.dll
  3. Register the assembly in the registry by adding a string value under

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IIS Extensions\MSDeploy\1\Providers\batch

The string value should point MSDeploy to your DeploymentProviderFactory, your namespace and, finally, your provider with assembly info. For the batch provider, the following string registry value needs to be added: “MSDeployCustomProviders.BatchProviderFactory, BatchProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a0b65de31a9f7a07, processorArchitecture=MSIL", where

  • MSDeployCustomProviders – is the namespace containing both the factory and provider, and
  • BatchProviderFactory – is the factory, and
  • BatchProvider + the rest – assembly info, which you can get by running the following:

    gacutil /l BatchProvider

For your convenience, register.bat is provided to do both (which runs every time the project is compiled according to project properties: in Visual Studio go to Project Properties-->Build Events and see that register.bat is called as a Post-Build event)

The Internals of BatchProvider

  • GetAttributes method is called on both source and destination to validate the object (think of performing a dump) without taking any action. If the object is invalid or if the object requires an action (in the example of the batch file provider, we need to run its commands in a shell program in a separate process), the method will throw a DeploymentException to make sure Add method is called. Finally, we want the code to take an action only when it is called on a destination object, which is insured by the following condition:

    if (this.BaseContext.IsDestinationObject)

  • Add method insures that the object is valid. Think of this method as a “Make valid” method that requires an action, since it is called only on a destination object. Destination objects will always be the objects that require an action, since dump can be performed only on source objects. Which makes sense, because in the command line, dump can be performed only with –source switch:

    msdeploy –verb:dump –source:<destination>

  • GetStream method is called when the source is getting synced to an archive directory (archiveDir provider) or a package (package provider). For example, this method will get called whenever the following commands are executed:

    msdeploy –verb:sync –source:batch=”myBatchJob.bat” –dest:archiveDir=c:\backup
    msdeploy –verb:sync –source:batch=”myBatchJob.bat” –dest:package=c:\backup.zip
    msdeploy –verb:sync –source:manifest=”manifestWithBatchInIt.xml” –dest:package=c:\backup.zip

    In GetStream method, the FileStream is returned, so that MSDeploy can attach a batch file to an archive or package as a simple text file.


You can tweak the provider to suit the task you have in mind. For example, you might want to tweak ProcessStartInfo of the process that will execute the batch file commands to control its behavior during sync. You might want to redirect output and error streams of the process to log the results of execution.

Please feel free to post any comments and questions.


Comments

  1. Microsoft Web Deployment Team Blog
    February 3, 2010

    During the RC timeframe of Web Deploy, we published a couple of sample custom providers that help you

  2. geoffmcgrath
    February 9, 2010

    Heh, doesn't compile...From the output window:

    BatchProvider.cs(64,25): error CS0246: The type or namespace name 'DeploymentAttribute' could not be found (are you missing a using directive or an assembly reference?)

    BatchProvider\BatchProvider.cs(104,25): error CS0246: The type or namespace name 'DeploymentObjectFlags' could not be found (are you missing a using directive or an assembly reference?)

Submit a Comment