Umbraco Forms deployment process - umbraco

I am using Umbraco Forms and do not want that the forms included on the development environment are included on the production environment; however I would like them to be included in source control.
Therefore my current setup includes the files under source control as per standard; however to exclude the forms data (App_Plugins/UmbracoForms/Data) I excluded the folder from the project (.CSPROJ). The problem is that after publishing (to file), the data files are always being included anyway, even if they are excluded.
Is there something else going on in the build process that is copying these files to the publish directory?

This issue that App_Plugins get published is actually configured by the UmbracoCms package from NuGet. It allows you to publish the project including Umbraco. But it adds additional folders as well. When installing Umbraco on the project, it adds 2 Import to the .csproj file.
<Import Project="..\packages\UmbracoCms.{version_number}\build\UmbracoCms.props" Condition="Exists('..\packages\UmbracoCms.{version_number}\build\UmbracoCms.props')" />
<Import Project="..\packages\UmbracoCms.{version_number}\build\UmbracoCms.targets" Condition="Exists('..\packages\UmbracoCms.{version_number}\build\UmbracoCms.targets')" />
In this UmbracoCms.props file it refers to the property CopyAllFilesToSingleFolderForPackageDependsOn that is defined in MSBuild.
This task gets executed when the files are being packaged.
Within this property, it mentions the task AddUmbracoFilesToOutput.
This task is found in the UmbracoCms.targets.
Within this task, it defines a task named FilesForPackagingFromProject which is used in WebDeploy. In this task it uses all the Elements named CustomFilesToInclude. As you can see there is the following line:
<CustomFilesToInclude Include=".\App_Plugins\**\*">
<Dir>App_Plugins</Dir>
</CustomFilesToInclude>
It does not matter if you exclude the files, it will always be adding this because of the above line.
How to resolve this?
We cannot change this UmbracoCms.targets file so we have to take other options since we don't want to change the way Umbraco has specified these files.
What we can do is specifying excludes ourselves by doing this thesame way Umbraco did.
Add a new Target, an ItemGroup and add the element ExcludeFromPackageFolders, specify the Include attribute and fill this with the values.
<Target Name="ExcludeUmbracoFormsData">
<ItemGroup>
<ExcludeFromPackageFolders Include="App_Plugins\UmbracoForms\Data">
</ExcludeFromPackageFolders>
</ItemGroup>
</Target>
Then add a PropertyGroup with the Property CopyAllFilesTOSingleFolderForPackageDependsOn and specify the name of the target you just created.
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
ExcludeUmbracoFormsData;
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
Alternative
If you are using UmbracoForms 4.4+ you can define a different type of storage for your forms: https://our.umbraco.com/documentation/Add-ons/UmbracoForms/Developer/IFileSystem/

It sort of depends on how you are doing the publish. If you are just publishing through visual studio, you can add some parameters to the PropertyGroups of your csproj.
<ExcludeFoldersFromDeployment>App_Plugins\UmbracoForms\Data</ExcludeFoldersFromDeployment>
There is also some talk about doing this here: Web Deployment FAQ. If you do some googling about ExcludeFoldersFromDeployment you'll find some other ways to do this if you are calling MSBuild yourself.
/p:ExcludeFoldersFromDeployment="App_Plugins\UmbracoForms\Data"

Related

How to generate a file with version control information (TFS) during build

I'm tired of not knowing what builds web application is built from when an issue is presented to me by QA. My proposed solution is to generate some static content as part of the build process that has useful information in it. Somebody could reference that file manually on the server and I think it would be nice to offer the ability the HTTP GET the content as json perhaps as part of the API.
Seems simple right? I've done a lot of looking into doing this with Subversion in the past but I'm not familiar with the options for TFS. I realize that I'm really looking for two things, one to harvest the TFS information such as the repository, branch, changeset number, ... as well as a way to write content to a file all within a standard build process. Are there any existing MSBuild targets or tools I can pull in using something like Nuget to ensure that this is done for all builds whether they are local dev builds or ones done through a CI server which don't require any extra configuration or steps by the dev or the one setting up the CI server environment? What I'm hoping is that this is a common enough pattern that maybe somebody has already done this exact thing and packaged it for reuse or that the pieces are simple enough to piece together in a way that can be repeated as a general pattern for various types of .NET projects.
UPDATE: I realized that one issue with the proposed solution is that whatever static file is generated, it would have to be added as a reference to the project in order to be picked up by the build process as content so that it is copied/published properly along with the rest of the web application. Perhaps a broken reference can be added to the project ahead of time that would be fulfilled after the project is built at least once. This is reminiscent of the old way that Package Restore used to work with NuGet.
Related resources:
MSDN - Code Generation in a Build Process
StackOverFlow - MSBuild to copy dynamically generated files as part of project dependency
StackOverflow - How to programmatically get information about branches in TFS?
StackOverflow - It is possible to get TFS change set number from the local file system?
StackOverflow - tf.exe info /version:T does not get latest
The version control information is already generated in environment variables, you just need to write some simple command to read them from the environment variables. Check following links to see if these information meets your requirement:
For vNext build: Predefined variables.
For XAML build: TF_BUILD environment variables.
To include the generated file, you can refer to this question for details: How do you include additional files using VS2010 web deployment packages?
Here is what I've come up with which is working for now:
<Target Name="BeforeBuild">
<PropertyGroup>
<ProgramFiles32>$(MSBuildProgramFiles32)</ProgramFiles32>
<VS14Dir>$(ProgramFiles32)\Microsoft Visual Studio 14.0</VS14Dir>
<TF Condition="Exists('$(VS14Dir)')">$(VS14Dir)\Common7\IDE\TF.exe</TF>
<TfCommand>"$(TF)" vc info . > version.txt</TfCommand>
</PropertyGroup>
<Message Importance="High" Text="Creating version.txt: $(TfCommand)" />
<Exec Command="$(TfCommand)"></Exec>
</Target>
<ItemGroup>
<Content Include="$(SolutionDir)\version.txt">
<Link>%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
This invokes the tf.exe console application with the args vc info . which gets version control information for the current directory and then uses >> version.txt to pipe the output to a file. There are a probably a bunch of improvements that could be made on this but it's a start. Next, I'll have to find some way to include the generated version.txt file as content within the project.
UPDATE: It looks like tf info only gives info about the specified directory and not about the working copy. I'm looking around for alternatives again.

TFS Continous build custom Drop folder template

I am trying to implement continous build process, if i look at the XAML in the sequence Drop Folder I want to specify a custom template
that is I do not want all the files to be dropped in one folder,
I have to create a folder structure like Folder1, Folder2, inside root folder.
Based on file extension files have to be dropped to particular foldder
any point how to achieve this,
If you're happy modifying the TFS build templates then Torbjörn's answer is definatly the way to go. Customising the build template will give you complete control of the output. However this can be overkill, especially if you're not familiar with WF and the internals of Team Build. An alternative is to write some msbuild which will run as part fo the build.
To do this create a file called "DropTidy.proj" and edit the file so that it looks something like this
<Project DefaultTargets="CopySQLReleaseFiles" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<Target Name="CopySQLReleaseFiles">
<ItemGroup>
<SqlBuildOutput Include="$(OutDir)\*.sql" />
</ItemGroup>
<Copy SourceFiles="#(SqlBuildOutput)" DestinationFolder="$(OutDir)\SQL" />
</Target>
</Project>
The example above will copy all files with an extensions of "sql" in to a folder called "SQL". $(OutDir) is the working folder used by team build that relelates to the "Binaries" folder in the build workspace on your build agent
Check the file in to TFS and then add it to your "Items to Build" list in the Team Build Definition. Make sure that it's the last "Solution" in the list so that it runs after the other solutions in your build. Also make sure that the folder you checked the proj file in to is part of your builds workspace.
Run your build and you should see a new folder called SQL in your drop location.
If you're using the default build process template (or a derivative of), the actions for copying to DropFolder are inside Finally block of Try Compile, Test and Associate Changesets and Work Items. You will have to replace that single Copy to Drop Location action with your custom sequence. The FindMatchingFiles can be used to select a set of files based on a search criterium.
One problem will arise when trying to copy single items; TFS build activities does not have an action for that; only for CopyDirectory. You can set up a InvokeProcess, alternatively add Community TFS Build Extensions from where you'll get Robocopy and Powershell actions to support such tasks.
If you're using the basic DefaultTemplate, I'd strongly advise you to make your changes in a copy of it and use that for your builds.

What are some good ways to distribute a common ant file to be included in builds?

I work in a group where we produce many small apps, and use ANT for our build processes.
We would like to have some of our commonly used directives housed in a common way. Currently, we require a mapped drive to a common location, and use
<import file="${env.MAPPED_DRIVE}/common_directive.xml">
There must be a better way to distribute a common ant file to include in many projects without having to map a drive. Do you have any other suggestions?
Import is a "top level" directive, which means it won't work inside of a target. Therefore, I cannot simply create a target that downloads the file, and then import it.
If you are using ANT 1.8+, you could specify a URL and host the common build fragment on a website.
Since Ant 1.8.0 the task can also
import resources from URLs or
classpath resources (which are URLs,
really). If you need to know whether
the current build file's source has
been a file or an URL you can consult
the property ant.file.type.projectname
(using the same example as above
ant.file.type.builddocs) which either
have the value "file" or "url".
I've worked out a solution that creates a jar file containing our reusable build scripts in a directory, say com/example/ant/sharedbuild, which can be imported in Ant 1.8:
<project>
<import>
<javaresource name="com/example/ant/sharedbuild/java.xml">
<classpath location="../../../../target/ant-shared-build.jar" />
</javaresource>
</import>
</project>
In my case this defines all of the "public" targets for the project to do a java-based build.
The syntax is a little verbose, especially as I add more and more include files (say, to add the ability to create an OSGi jar). By adding an antlib.xml that contains a combination of a macrodef and scriptdef to the jar file (in the same directory as the shared build scripts), the build file can now look like this (and now also creating an OSGi jar bundle):
<project xmlns:build="antlib:com.example.ant.sharedbuild">
<taskdef uri="antlib:com.example.ant.sharedbuild"
classpath="../../../../target/ant-shared-build.jar" />
<build:build using="java, jar, bundle" />
</project>
Unfortunately, I can't share the code in the macrodef or scriptdef, but really it isn't hard: a little javascript to parse the using attribute and loop over each, derive a file name from it, and import.
I reference the jar file in a fixed location (relative to my project) on my hard drive. I think we can do better. Ideally, I'd like to fetch a (versioned!) jar file from a central location. Since we're already using Ivy (with an HTTP repository) we can publish the jar file there (again, with a version) and fetch it directly from there:
<project xmlns:build="antlib:com.example.ant.sharedbuild">
<property name="ant.shared.build.jar.file"
location="${user.home}/ant/ant-shared-build-1.5.3.jar" />
<get src="http://repo.example.com/.../ant-shared-build-1.5.3.jar"
dest="${ant.shared.build.jar.file}"
skipexisting="true" />
<taskdef uri="antlib:com.example.ant.sharedbuild"
classpath="${ant.shared.build.jar.file}" />
<build:build using="java, jar, bundle" />
</project>
There are some problems with this:
It's getting verbose again.
The verbosity is repeated for every build.xml.
There's a lot of repeated boilerplate, especially the version number.
To mitigate these problems, in each directory containing a build.xml I also have a bootstrap.xml (the name doesn't really matter). Each build.xml then includes this file:
<project xmlns:build="antlib:com.example.ant.sharedbuild">
<include file="bootstrap.xml" />
<build:build using="java, jar, bundle" />
</project>
Each bootstrap.xml, at a minimum, includes it's parent's bootstrap.xml:
<project>
<include file="../bootstrap.xml" />
</project>
The top-level bootstrap.xml (the root), then does the work of getting the jar file and creating the custom tasks, as above:
<project>
<property name="ant.shared.build.version"
value="1.5.3" />
<property name="ant.shared.build.jar.filename"
value="ant-shared-build-${ant.shared.build.version}.jar" />
<property name="ant.shared.build.jar.file"
location="${user.home}/ant/${ant.shared.build.jar.filename}" />
<get src="http://repo.example.com/.../${ant.shared.build.jar.filename}"
dest="${ant.shared.build.jar.file}"
skipexisting="true" />
<taskdef uri="antlib:com.example.ant.sharedbuild"
classpath="${ant.shared.build.jar.file}" />
</project>
Though not directly related to the question, I'm actually reworking the macrodef and scriptdef into a custom ant task, because I want to be able to support a syntax that looks like this:
<project xmlns:build="antlib:com.example.ant.sharedbuild">
<include file="bootstrap.xml" />
<build:build>
<using>
<java />
<bundle>
<manifest>
Import-Package: *,org.joda.time;version="[1.6.0,1.6.0]"
Bundle-Activator: com.example.time.impl.Activator
</manifest>
</bundle>
</using>
</build:build>
</project>
I should point out that just creating a redistributable build doesn't mean it's going to be useful. You still need to put in the time and effort to create a cohesive, modular, consistent implementation in line with a design of similar characteristics. This is more important as you need to share scripts across projects, across teams, across organizational boundaries, etc.
In conclusion, by creating a jar file, with a version number, that can be distributed independent of a specific file location or an SCM tool we can get real shared but reproducible builds.
Dominic Mitchell's comment about the URL reference being a bad idea if you want repeatable builds got me thinking...
Another solution to consider, if you are using SVN for version control, is to create an SVN Externals Definition that points to the common_directive.xml.
Then, just use a relative path for your ANT import file reference.
Sometimes it is useful to construct a
working copy that is made out of a
number of different checkouts. For
example, you may want different
subdirectories to come from different
locations in a repository or perhaps
from different repositories
altogether. You could certainly set up
such a scenario by hand—using svn
checkout to create the sort of nested
working copy structure you are trying
to achieve. But if this layout is
important for everyone who uses your
repository, every other user will need
to perform the same checkout
operations that you did.
Fortunately, Subversion provides
support for externals definitions. An
externals definition is a mapping of a
local directory to the URL—and ideally
a particular revision—of a versioned
directory. In Subversion, you declare
externals definitions in groups using
the svn:externals property. You can
create or modify this property using
svn propset or svn propedit (see the
section called “Manipulating
Properties”). It can be set on any
versioned directory, and its value
describes both the external repository
location and the client-side directory
to which that location should be
checked out.
The convenience of the svn:externals
property is that once it is set on a
versioned directory, everyone who
checks out a working copy with that
directory also gets the benefit of the
externals definition. In other words,
once one person has made the effort to
define the nested working copy
structure, no one else has to
bother—Subversion will, after checking
out the original working copy,
automatically also check out the
external working copies.

TFS with different binaries folder for different projects

I've got a solution with Silverlight projects, a couple Web applications and some Windows service and their small Winforms test applications.
When I build it using TFS it puts all binary files in the Binaries folder. It also creates a _PublishedWebsites folder where it puts the web applications ready for deployment.
What I would like is for a few of the projects to have their ouput in a separate directory in the Binaries folder. I want the files that I would normally find in the bin\Release folder to be there.
I looked long and hard and could only find scarce documentation on how to achieve that and only for TFS 2008. There's a good article there link text and another entry for VS 2010 there link text. However, none of these work :-(
It seems that the build ignores the <OutputPath> property. I tried fiddling with the <AfterBuild> property but unfortunately if I use the $(OutDir) property I get ALL the files in the Binaries directory and not only the ones that just got compiled.
At the moment I'm setting up a separate build that only has the projects I'm interested in that get compiled but I would really like to have all the files needed for the release built all at once.
EDIT: I didn't make it clear enough but I'm using the latest version of TFS (TFS 2010 RTM). I set up <OutputPathDir> on the project level as explained in the links that I provided.
Cheers.
In your build definition (.proj) file, check that
<Project>
<PropertyGroup>
<CustomizableOutDir>true</CustomizableOutDir>
</PropertyGroup>
</Project>
Also, you may run into some problems if you're trying to compile what was once a "website" project type (created from File->New->Website->ASP.NET Webiste). They seem to override the output directory every time. We had to convert some of those to class libraries instead.

What's the best way to get TFS to output each project to its own directory?

I'm putting a large codebase into Team Foundation Server. I would like the build process to create a "ready to deploy" build of our projects.
The normal way we've been doing this is to have each project's output be in its own folder. So, for example, we wind up with something like
C:\project1\
assembly1.dll
assembly2.dll
project1.exe
project1.exe.config
C:\project2\
assembly2.dll
assembly3.dll
project2.exe
project2.exe.config
C:\project3\
assembly1.dll
assembly3.dll
project3.exe
project3.exe.config
Which is the way we like it.
TFS, though, seems to want to stick everything in the same directory.
C:\output\
assembly1.dll
assembly2.dll
assembly3.dll
project1.exe
project1.exe.config
project2.exe
project2.exe.config
project3.exe
project3.exe.config
which, although it saves some amount of disk space (the assemblies are only there one time each) is not how we want it.
What's the best way to specify where TFS/MSBuild should put the output files? Do I need to edit sln/csproj files individually to achieve this or can I do it in the TFSBuild.proj file? (i.e., in a MSBuild-specific file)
I just blogged another method here:
http://mikehadlow.blogspot.com/2009/06/tfs-build-publishedwebsites-for-exe-and.html
but if you can't be bothered to follow the link, here it is in full:
It’s generally good practice to collect all the code under your team’s control in a single uber-solution as described in this Patterns and Practices PDF, Team Development with TFS Guide. If you then configure the TFS build server to build this solution, it’s default behaviour is to place the build output into a single folder, ‘Release’.
Any web application projects in your solution will also be output to a folder called _PublishedWebsites\. This is very nice because it means that you can simply robocopy deploy the web application.
Unfortunately there’s no similar default behaviour for other project types such as WinForms, console or library. It would be very nice if we could have a _PublishedApplications\ sub folder with the output of any selected project(s). Fortunately it’s not that hard to do.
The way _PublishedWebsites works is pretty simple. If you look at the project file of your web application you’ll notice an import near the bottom:
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />
On my machine the MSBuildExtensionsPath property evaluates to C:\Program Files\MSBuild, if we open the Microsoft.WebApplication.targets file we can see that it’s a pretty simple MSBuild file that recognises when the build is not a desktop build, i.e. it’s a TFS build, and copies the output to:
$(OutDir)_PublishedWebsites\$(MSBuildProjectName)
I simply copied the Micrsoft.WebApplication.targets file, put it under source control with a relative path from my project files and changed _PublishedWebsites to _PublishedApplications and renamed the file CI.exe.targets. For each project that I want to output to _PublishedApplications, I simply added this import at the bottom of the project file:
<Import Project="<your relative path>\CI.exe.targets" />
You can edit CI.exe.targets (or whatever you want to call it) to do your bidding. In my case, the only change so far is to add a couple of lines to copy the App.config file:
<Copy SourceFiles="$(OutDir)$(TargetFileName).config" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" />
There’s a lot of stuff in Microsoft.WebApplication.targets that’s only relevant to web applications and can be stripped out for other project types, but I’ll leave that as an exercise for the reader.
TFS 2012+
I like this solution...
Edit your build definition. Under Process section, set MSBuild arguments to
/p:GenerateProjectSpecificOutputFolder=true
Like this:
By default each project file (*.csproj, *.vbproj, etc.) specifies a default output directory (which is usually bin\Debug, bin\Release, etc.). Team Build actually overrides this so that you're not at the whim of what properties the developer sets in the project file but also so that Team Build can make assumptions about where the outputs are located.
The easiest way to override this behaviour is to set CustomizableOutDir to true in the SolutionToBuild item group as shown here:
<ItemGroup>
<SolutionToBuild Include="$(BuildProjectFolderPath)\path\MySolution.sln" />
<Properties>CustomizableOutDir=true</Properties>
</SolutionToBuild>
</ItemGroup>
This will make the drop folder structure roughly match what you would get locally if you built the solution.
This method is definitely preferable to overriding the Core* targets which can cause upgrade issues.
For each SolutionToBuild node, set the property OutDir to $(OutDir)\SubFolder
For example:
<ItemGroup>
<SolutionToBuild Include="Project1.sln" >
<Properties>OutDir=$(OutDir)\Project1\</Properties>
</SolutionToBuild>
<SolutionToBuild Include="Project2.sln" >
<Properties>OutDir=$(OutDir)\Project2\</Properties>
</SolutionToBuild>
<SolutionToBuild Include="Project3.sln" >
<Properties>OutDir=$(OutDir)\Project3\</Properties>
</SolutionToBuild>
<ItemGroup>
(This works in TF2008, but not TF2005.)
I'm a bit late to the party answering this question but there is a very simple way to implement Mike Hadlows answer. Someone has written a nuget package that does exactly what Mike talks about. You can find it here: http://www.nuget.org/packages/PublishedApplications
Update for TFS 2010 (and upcoming TFS 2012). Jason Stangroome has written a nice blog post outlining how to do this.
https://blog.stangroome.com/2012/02/03/override-the-tfs-team-build-outdir-property/
Override the TFS Team Build OutDir property
Update: with .NET 4.5 there is an easier way.
A very common complaint from users of Team Foundation Server’s build system is that it changes the folder structure of the project outputs. By default Visual Studio puts all the files in each project’s respective /bin/ or /bin// folder but Team Build just uses a flat folder structure putting all the files in the drop folder root or, again, a // subfolder in the drop folder, with all project outputs mixed together.
Additionally because Team Build achieves this by setting the OutDir property via the MSBuild.exe command-line combined with MSBuild’s property precedence this value cannot easily be changed from within MSBuild itself and the popular solution is to edit the Build Process Template *.xaml file to use a different property name. But I prefer not to touch the Workflow unless absolutely necessary.
Instead, I use both the Solution Before Target and the Inline Task features of MSBuild v4 to override the default implementation of the MSBuild Task used to build the individual projects in the solution. In my alternative implementation, I prevent the OutDir property from being passed through and I pass through a property called PreferredOutDir instead which individual projects can use if desired.
The first part, substituting the OutDir property for the PreferredOutDir property at the solution level is achieved simply by adding a new file to the directory your solution file resides in. This new file should be named following the pattern “before..sln.targets”, eg for a solution file called “Foo.sln” then new file would be “before.Foo.sln.targets”. The contents of this new file should look like this. Make sure this new file gets checked-in to source control.
The second part, letting each project control its output folder structure, is simply a matter of adding a line to the project’s *.csproj or *.vbproj file (depending on the language). Locate the first element inside the project file that doesn’t have a Condition attribute specified, and the locate the corresponding closing tag for this element. Immediately above the closing tag add a line something like this:
<OutDir Condition=" '$(PreferredOutDir)' != '' ">$(PreferredOutDir)$(MSBuildProjectName)\</OutDir>
In this example the project will output to the Team Build drop folder under a subfolder named the same as the project file (without the .csproj extension). You might choose a different pattern. Also, Web projects usually create their own output folder under a _PublishedWebSites subfolder of the Team Build drop folder, to maintain this behaviour just set the OutDir property to equal the PreferredOutDir property exactly.
You can verify if your changes have worked on your local machine before checking in simply by running MSBuild from the command-line and specifying the OutDir property just like Team Build does, eg:
msbuild Foo.sln /p:OutDir=c:\TestDropFolder\
You could have one buildscript per project, that would do exactly what you want.
Just create a new TFSBuild file, add the projects you want to have built to the itemgroup(in the order you want them built), set where you want the output to be. This is done by overriding the - property in your TFSBuild file.
But I also agree with the previous poster - why don't you just run with a single build script, and add a zip-task at the end? Maintaining a buildscript per project does add maintenance overhead...
Sling this in a propertygroup:
<CustomizableOutDir>true</CustomizableOutDir>
It'll override the global 'CustomizableOutDir' property which, by default, is set to False. Setting this in the SolutionToBuild's properties will not work.
You achieve this by overriding the default CoreDropBuild target implementation.
In your TFSBuild.proj file (by default stored under TeamBuildTypes/<Build Type>) add the following target:
<!-- Override default implementation -->
<Target
Name="CoreDropBuild"
Condition=" '$(SkipDropBuild)'!='true' and '$(IsDesktopBuild)'!='true' "
DependsOnTargets="$(CoreDropBuildDependsOn)">
...
</Target>
Within this target you can manipulate the output as you want it. The default is to just copy everything from $(BinariesRoot)\$(BuildType) to $(DropLocation)\$(BuildNumber).
I normally use the Microsoft.Sdc.Tasks project for file copying capabilities.
Simple Solution:
Replace all <SolutionToBuild> nodes with <SolutionToPublish>. This will of course only work for publishable projects (e.g. Web projects and applications), not for library projects.
As simple as that :)

Resources