Skip to main content

Quickly and Easily Deploy Websites/Web Services with TFS Build via Web Deploy (MSDeploy)


When I first started deploying code from TFS I took the simple approach and created a batch file and deployed the websites via RoboCopy. I’m a very “Keep it simple” kind of guy, so this worked for us for a long time and so nothing was changed.

With my most recent project however, we were deploying code over a slow VPN tunnel from our servers in Chicago to servers located in Europe. Due to this, the RoboCopy was taking over 4.5 hours to complete. I needed a better/faster way so I started looking into Web Deploy (MSDeploy). I was able to get it working fairly easily and I was pleasantly surprised how easy it was to get it working, and how much time its saved me! I can now deploy the code in less than 20 minutes!

I’ve outlined the process in detail below, but in general you only need to do this:

  • Add MSBuild parameters to your automated build
  • Customize the deployment parameters for the website
  • Create a batch file to an auto-generated MSDeploy script
  • Execute the batch file from the automated build


Note: In order to use MSDeploy, you need to install MSDeploy on the destination server. Details can be found on the Web Deploy/MSDeploy website here:

Step 1: Create an automated Build in TFS

This is obvious, but worth mentioning. If you don’t have an automated build, you can’t do automated deployment. here is an MSDN Article that walks you through it:

Kick off your build and verify that it builds and deploys the websites properly. You can do this by making sure the build completes properly and that the code is moved out to the code drop location. The code should be in the following location:

<Code Drop Location from Build Defaults Tab>\<Build Name>\<BuildName>_<timestamp>\PublishedWebsites



Step 2: Customize the build for MSDeploy

After the build is created, there are a few MSDeploy specific changes you need to do.

1. For the Default Template, create a new template by clicking on “New…”, selecting the Default template, naming it and clicking “OK”. This is the template we’ll be editing later on.


2. On the “Process” tab, you need to enter the following for the MSBuild Arguments:

/p:DeployOnBuild=True /p:Configuration=Release


Step 3: Kick off the build and verify MSBuild Arguments:

Now that the MSDeploy stuff has been added, you want to kick off another build. When it completes you should now start seeing some “_Package” folders in the Code Drop Location:


If you don’t see these, then go back to steps 1 and 2 and make sure you’ve got everything set up properly.

Take a look at the contents. You can see that TFS/MSBuild take care of a lot of the heavy lifting.


  • Deploy.cmd: This is a batch file that can be executed to publish code to a server that has Web Deploy installed on it. You can open it and take a look to get an idea of what its doing. Its some pretty cool stuff
  • SetParameters.xml: This is an xml file that allows you to set some specific parameters for the deployment  like IISWebsite name, etc. We’ll be using this file later to tell MSDeploy where to put the code.
  • Sourcemanifest.xml: Config file used by MSDeploy to Locate where the code files are
  • zip file: Compressed version of the published website. This is what is deployed to the server during deployments


Step 4: Save off “SetParameters.xml” files

I like using batch files for deployments and I like to save them on the build server so they are easily executed during deployments. When I do this, I add folders into the Code drop location for each build definition and create a new folder called “Batches”. We’ll need to save off the SetParameters.xml files as well, so lets create another folder in the Batches folder called SetParameters. Grab the SetParameters.xml file from step 3 and copy it into this folder.


Now we need to customize this XML file for our deployment.

Open the SetParameters.xml file in a text editor. You’ll see a “setParameter” XML node where the IIS Web Application name is being set. Update this to match the Website/Web app in IIS on the server where this will be deployed:

In my example, the WebService is actually deployed on the server to the Default Web Site –> NewsService location

IIS on the server:




Step 5: Create a batch file to execute the Deployment

Now that we have the Package folder being created and we’ve customized our XML file, we need to set up a batch file to execute MSDeploy and have it published to the server. The auto generated deploy.cmd file comes in extremely handy.

Again, we’ll leverage the “Batches” folder on the build server.

Create a new batch file called “RunDeployment.cmd” in the Batches folder and add the following lines into it:


  1. Here we set up variables used to execute the MSDeploy. I use variables so that we can easily change things like server names, etc. without changing the actual MSDeploy calls
    • _xcopyFlag: normal xCopy flags used to silently overwrite files via batch files
    • _location: this trims extra quotes from the location parameter passed in. (We’ll pass in this from the Deployment workflow later on)
    • _logfile: Sets up a log file. Very useful for troubleshooting/verification of deployments
    • _Server: name of the server were this will be deployed
    • svcname: name of the website/web service that is being deployed
  2. This moves the customized SetParameters.xml file back into the _Package folder to overwrite the auto generated one.
  3. This calls the deploy cmd file to execute the deployment.
    1. In my example, I’ve got a few extra flags for usename/password for security.
    2. There are other flags that can be used such as “-skip:objectName” that will ignore folders, but in this case we’ll keep it simple.

Step 7: Modify the Build workflow:

Now we need to make a few simple additions to the build workflow to call the batch file.

Open the Build template XAML file that was created in step 2. Typically these are stored in Source Control at $Project\BuildProcessTemplates:

When the workflow opens, add a new Sequence workflow after “Check in gated Changes..” step named “Deploy to Servers”


Open the Sequence object and drag an “InvokeProcess” task onto the surface:


Right click and select properties and enter the following information:


  • Arguments:The arguments we want to pass into the batch file
    • Example: """" + BuildDetail.DropLocation + "\_PublishedWebsites\" + """"
  • FileName:The location of the batch file created in step 5
    • Example: <Code Drop Location>\<BuildDefinition>\Batches\RunDeployment.bat”


Step 8: Run the build

Run the build and check your server. If the bits have been updated, you’ve been successful. If not, check the log file created by the batch file(filecopy.txt) and troubleshoot.

Important: Before you run the build, please make sure to backup the deployed folder on the server if you are concerned about losing anything. MSDeploy cleans up files on the server that aren’t part of the deployment, so if you have images or other files that are not part of the build, they will be deleted from the server. Also, run this on non-production environments first and hone this process down before you use it in production. If you build the batch files with parameters and variables, using MSDeploy in Staging/production environments will be easy.



While the information above may seem complex, most of the work is done by the auto generated files. Basically you only need to update your build with the MSBuild parameters, create a batch file and execute the batch file from the build.

there is a lot of power in MSDeploy that is not being used at this point, but I’ll post something else if I come across anything else useful



  1. Shouldnt there be an easy way to preserve the etParameters.xml by now? I find it odd that I need to manually swap that out every time i run a build.

  2. I believe so, at least for some of them. I think you can pass some of the values in as parameters to the MSDeploy Script.


Post a Comment

Popular posts from this blog

Build/Deploy Windows service with TFS

Building and deploying a web service or website via TFS is pretty straight forward, but automatically deploying a windows service or console application takes a b it of setup. I’ve outlined the steps below to get your service deployed. Step 1: Set up Automated Build and MSDeploy on the Target server. If you are doing any sort of automated build/deploy I recommend using MSDeploy. You can follow steps 1-3 from a previous post here.Step 2: Edit the .csproj fileThe project file for the app you are trying to deploy needs to be edited so that TFS will create a directory for the output of the project. Otherwise the project will be built, but the assemblies will be placed in the code drop location with no organization to it.To edit the file, go to the open file dialog and locate the csproj file. Select it but don’t click “Open. Instead click on the dropdown arrow next to the Open button, select “Open with”, and choose the XML (Text) editor as shown:Once the file is open, add the following “Pr…

Repository Pattern with Cross Table Objects

In a recent post, I mentioned one of the advantages of using Entity Framework in your application is that you can build a generic repository class very easily. Of course, its not realistic to think that all access to the data will be a single table at a time. Most often it’s the case where you need to return data that spans multiple tables. I’m  going to show you how I created a simple repository class that spans tables.Creating the Summary/DTO ObjectThe first thing I like to start with is to create the simple POCO object that will be used to transport the data. This is essential to define first so that you do not get caught up in data structures, but instead define the data as the application is going to need it. In the case with my database, I have a table called “Avail” that contains a ton of foreign keys to a contact table. I needed to display this data, but instead of a bunch of foreign keys, I needed to display the actual names of people. etc. I ended up defining the object as f…