Publishing Web Sites in TeamBuild

We have been seeing a huge customer request on how to publish a website in TeamBuild build process. Below, I have attempted to detail what I did to get this to work. This should help you get started!

I started with the goal of creating a virtual directory on the build machine and copying the website content built by my build process to this virtual directory. To achieve this, I need to override the target AfterCompile and include CreateVirtualDirectory and Copy tasks. I found .NET SDC toolkit (GDN2[1].0.051004.000.zip) on gotdotnet portal that offers a powerful set of msbuild tasks for enterprise builds. It includes tasks to create and manage websites. I’ve downloaded this toolkit onto my machine and tried to find the minimal set of files that I need to create virtual directory. The task is called Microsoft.Sdc.Tasks.Web.WebSite.CreateVirtualDirectory defined in Microsoft.Sdc.Tasks.dll. I located this binary at GDN2[1].0.051004.000\Microsoft.Sdc.Tasks\MainTempGDN\Install\bin.

Now, I’ve added the following script to my TfsBuild.proj:

<PropertyGroup>

<WebDeployFolder>d:\StagingFolder</WebDeployFolder>

<WebSiteSrcName>WebSite1</WebSiteSrcName>

<WebDeployName>WebSite1</WebDeployName>

<WebSitePreCompiledSrcFolder>$(SolutionRoot)\..\Binaries\.NET\Debug\_PublishedWebSites\$(WebSiteSrcName)</WebSitePreCompiledSrcFolder>

</PropertyGroup>

<UsingTask TaskName="Microsoft.Sdc.Tasks.Web.WebSite.CreateVirtualDirectory" AssemblyFile="Microsoft.Sdc.Tasks.dll" />

<Target Name="AfterCompile">

<MakeDir Directories="$(WebDeployFolder)\$(WebDeployName)" />

<CreateVirtualDirectory VirtualDirectoryName="$(WebDeployName)" Path="$(WebDeployFolder)\$(WebDeployName)" />

<Exec Command="xcopy /y /e $(WebSitePreCompiledSrcFolder) $(WebDeployFolder)\$(WebDeployName)"/>

</Target>

I know that TeamBuild process compiles web sites to binaries location and I’ve selected Debug|.NET flavor to build. This is what WebSitePreCompiledSrcFolder is pointing to. All other properties are self explanatory. This script creates a staging folder, create a virtual directory under web site “Default Web Site” on my build machine pointing to this staging folder and copies my precompiled web site to this staging folder.

I then checked in TfsBuild.proj and Microsoft.Sdc.Tasks.dll and its dependent binary Microsoft.Sdc.Configuration.dll into my build type folder ($/<TeamProject>/TeamBuildTypes/<BuildType>) and kicked off a build!

You might also encounter the following error that I had seen :

error MSB4062: The "Microsoft.Sdc.Tasks.Web.WebSite.CreateVirtualDirectory" task could not be loaded from the assembly d:\builddir\ScoutingTest\BuildTypeForWeb\BuildType\Microsoft.Sdc.Tasks.dll. Could not load file or assembly 'Microsoft.Sdc.Configuration, Version=1.2.5000.0, Culture=neutral, PublicKeyToken=e24a7ed7109b7e39' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A) Confirm that the <UsingTask> declaration is correct, and that the assembly and all its dependencies are available.

Seems like, they have missed signing this binary. I had to register this binary to my ‘skip verification’ list on my build machine (open .NET SDK command prompt and run “sn –Vr Microsoft.Sdc.Configuration.dll”) to get this to work.

Another thing to note is, the TeamBuild service account (the account with which the TeamBuild service is running) needs administrator access on the machine where the virtual directory is created. You will see an error similiar to below in case it was not administrator:

MSBUILD : warning : A task error has occured.

MSBUILD : warning : Message = Unknown error (0x80005000)

MSBUILD : warning : VirtualDirectoryName = mydemosite

MSBUILD : warning : Path = c:\Publish\mywebsite

MSBUILD : warning : MachineName = mymachine

MSBUILD : warning : WebSiteName = mydemosite

MSBUILD : warning : AppPoolId = DefaultAppPool

MSBUILD : warning : AppCreate = False

MSBUILD : warning : AnonymousUserName = <String.Empty>

MSBUILD : warning : AnonymousUserPassword = <String.Empty>

MSBUILD : warning : UncUserName = <String.Empty>

MSBUILD : warning : UncPassword = <String.Empty>

MSBUILD : warning : AuthFlags = <String.Empty>

MSBUILD : warning : AccessFlags = <String.Empty>

MSBUILD : warning :

MSBUILD : warning : at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)

MSBUILD : warning : at System.DirectoryServices.DirectoryEntry.Bind()

MSBUILD : warning : at System.DirectoryServices.DirectoryEntry.get_IsContainer()

MSBUILD : warning : at System.DirectoryServices.DirectoryEntries.ChildEnumerator..ctor(DirectoryEntry container)

MSBUILD : warning : at System.DirectoryServices.DirectoryEntries.GetEnumerator()

MSBUILD : warning : at Microsoft.Sdc.Configuration.Web.WebSite.GetIdentifierFromDescription(String machineName, String description)

MSBUILD : warning : at Microsoft.Sdc.Configuration.Web.WebSite.Load(String machineName, String description)

MSBUILD : warning : at Microsoft.Sdc.Tasks.Web.WebSite.CreateVirtualDirectory.InternalExecute()

MSBUILD : warning : at Microsoft.Sdc.Tasks.TaskBase.Execute()

 

It was not administrator in my case. So, I had to grant these permissions and restart TeamBuild service.

After completing these changes, my build process started creating a virtual directory and copying my newly build web site content to this folder. Yaahoo, I can now hit this website through my web testsJ

Let us examine the CreateVirtualDirectory in detail:

 

<CreateVirtualDriectory

VirtualDirectoryName="virtualDirectoryName"

Path="path"

MachineName="machineName"

AppPoolID="appPoolID"

AppCreate="appCreate"

WebSiteName="webSiteName"

AnonymousUserName="anonymousUserName"

AnonymousUserPassword="anonymousUserPassword"

UncUserName="uncUserName"

UncPassword="uncPassword"

AuthFlags="authenticationFlags"

AccessFlags="accessFlags"

/>

 

As you may have noticed, you can opt for a remote machine, point to any web site, point to an UNC share etc. This is a powerful task!

There are a bunch of useful tasks in Microsoft.Sdc.Tasks.Web namespace hierarchy. You can manage websites, ftp sites, and app pools etc pretty much do everything in web management.

Namaste!