Wix Installer Heat.exe error Parameter "exePath" is invalid - .net-core

I am building a self-contained .Net Core worker service which I run as a windows service. Now I want to create an installe using Wix, however when I try to harvest all the needed DLL's for installation I get the following error:
An error occurred loading a configuration file: The parameter 'exePath' is invalid.
I've read this post which states the heat.exe might be broken. But I downloaded the tools via NuGet (3.11.2) which should theoretically be fine. My Beforebuild target looks as following:
<Exec Command="dotnet publish ..\Parlando.PVS.PackingSlipService\Parlando.PVS.PackingSlipService.csproj -c $(Configuration) -r win10-x86" />
<ItemGroup>
<LinkerBindInputPaths Include="%(ProjectReference.RootDir)%(ProjectReference.Directory)bin\$(Configuration)\%(ProjectReference.TargetFrameworkIdentifier)\win10-x86\publish" />
</ItemGroup>
<HeatDirectory
DirectoryRefId="INSTALLFOLDER"
OutputFile="$(ProjectDir)\HeatGeneratedFileList.wxs"
Directory="..\Parlando.PVS.PackingSlipService\bin\Release\netcoreapp3.1\win10-x86\publish"
ComponentGroupName="HeatGenerated"
ToolPath="$(WixToolPath)"
AutogenerateGuids="True"
SuppressCom="True"
SuppressRegistry="True"
SuppressFragments="True"
SuppressRootDirectory="True"
NoLogo="true" />
<ItemGroup>
<Compile Include="$(ProjectDir)\HeatGeneratedFileList.wxs" Condition="'%(ProjectReference.IsDotnetSDKProject)' == 'True'" />
</ItemGroup>
This should generate a .wxs file that I reference in the Product.wxs file when installing the service. My product.wxs does so as followed:
<ServiceInstall
Id="ServiceInstaller"
Type="ownProcess"
Name="Parlando.PVS.PackingSlipService"
DisplayName="Parlando.PVS.PackingSlipService"
Description="Service installed by Parlando to create packingslips and invoices."
Start="auto"
Account="LocalSystem"
ErrorControl="normal" />
<ServiceControl
Id="ServiceInstaller"
Start="install"
Stop="both"
Remove="uninstall"
Name="Parlando.PVS.PackingSlipService" />
</Component>
<ComponentRef Id="HeatGenerated" />
How can i use the heat.exe in such a way that I can access the DLL list in my Product.wxs and install my service via MSI?

Apperantly this error has nothing to do with the provided settings for the Wix installer, but rather the machine that Wix is installed on.
After testing my program on a different machine, all worked fine.

Related

ASP.NET core RazorPages - No executable found matching command "dotnet-bundle"

I know - can see related questions for ASP.NET MVC projects & talk around project.json files but i'm using the default project with ASP.NET core with Razor pages & all i believe the equivalent file to edit is the *.csproj file - I've seen a few of the answers do relate to the *.csproj file & i have followed them with still no joy :/ Being new i can't add comments to those answers directly so thought a new post best..
Using VS-2017. Basic project created via /.NET Core/ASP.NET Core Web Application/"Web Application" (just in case i'm leading anyone astray) and with a single test edits made to site.css to test minification.
via NuGet package manager window confirmed BundlerMinifier.Core v2.6.362 is installed
.csproj file contents:
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BundlerMinifier.Core" Version="2.6.362" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.1" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="BundlerMinifier.Core" Version="2.6.362" />
</ItemGroup>
</Project>
Project saved and built.
When running "dotnet bundle" in the Package Manager Console i get result:
PM> dotnet bundle
dotnet : No executable found matching command "dotnet-bundle"
At line:1 char:1
+ dotnet bundle
+ ~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (No executable f..."dotnet-bundle":String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
PM>
i honestly have not further clue why this isn't working!??
Ideally all i want to do is incorporate custom css & js into the project, i'm led to believe this is the 'proper' way.. maybe there is a better (i.e. simpler) solution? No idea why this isnt part of the default template, assuming that the template is meant for beginners?..
THANKS!
This is a valid problem.
The root is that for some reason the executing directory is not set to the same as what you have selected in VS as the default project.
Try entering dir in package manager console. If you are not in your project directory, cd into your project and run dotnet bundle again.

Use 'gitinfo' MSBuild variable within ASP.NET website .pubxml file?

I am using the GitInfo nuget package from https://github.com/kzu/GitInfo to provide branch and commit information within my web application.
I have a publish profile set up to deploy to the filesystem and I'd like to include the git branch name in the path. I tried changing this line in the pubxml file:
<publishUrl>C:\Development\Web\Publish_$(GitBranch)</publishUrl>
...however the '$(GitBranch)' was ignored (website was successfully published to 'Publish_' folder). I am publishing using the 'Publish...' wizard in Visual Studio 2015.
My website vbproj file has the following imports and targets:
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
<PropertyGroup>
<PreBuildEvent />
<PostBuildEvent />
</PropertyGroup>
<Import Project="packages\GitInfo.2.0.3\build\GitInfo.targets" Condition="Exists('packages\GitInfo.2.0.3\build\GitInfo.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\GitInfo.2.0.3\build\GitInfo.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\GitInfo.2.0.3\build\GitInfo.targets'))" />
</Target>
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v‌​$(MSBuildToolsVersio‌​n)\WebApplications\M‌​icrosoft.WebApplicat‌​ion.targets" Condition="false" />
Is what I want to do possible?
Is what I want to do possible?
Open your website vbproj file after installed the NuGet package, you would notice that below code line:
<Import Project="packages\GitInfo.2.0.3\build\GitInfo.targets" Condition="Exists('packages\GitInfo.2.0.3\build\GitInfo.targets')" />
NuGet imported .targets files into project file that contain items, properties, targets, and tasks for GitInfo. These imported variables can only be accessed during build process. When you access it during the publish, you will get a null value. That is the reason why the value $(GitBranch) was ignored and website published to Publish_ folder.
As a workaround, you can custom a target to set the value $(GitBranch) to the environment variable, so that you can access it anytime.
See How to set envrionment variables in MSBuild file ? for more detail information.

How to get aspnet_compiler invoked from Visual Studio during build?

I want Visual Studio to precompile my ASP.NET application which is used as an Azure web role payload. So I've found this post that explains how to call aspnet_compiler to validate views.
I tried to add the following to "post-build event" of my ASP.NET application:
call "%VS100COMNTOOLS%\vsvars32.bat"
aspnet_compiler -v / -p $(ProjectDir)
or alternatively this (application name specified explicitly):
call "%VS100COMNTOOLS%\vsvars32.bat"
aspnet_compiler -v /ASP.NET-Application-ProjectNameHere -p $(ProjectDir)
In both cases when the build runs I see the following in the build output:
Setting environment for using Microsoft Visual Studio 2010 x86 tools.
Utility to precompile an ASP.NET application
Copyright (C) Microsoft Corporation. All rights reserved.
and clearly no precompilation happens because if I change any .aspx or .cshtml file "Build Action" to "None" it doesn't get to the Azure service package and the view no longer opens once the package is deployed to Azure.
How do I setup aspnet_compiler for precompiling from within Visual Studio?
If you want to use Asp.NET Compiler within your Visual Studio / msbuild then you can add
AspNetCompiler Task to your project file (.csproj/.vbproj) and set MvcBuildViews to true.
Example:
<Project>
<PropertyGroup>
<MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
<!-- ... -->
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<Message Text="Starting AspNetCompiler for $(ProjectDir)" Importance="high" />
<AspNetCompiler
VirtualPath="temp"
PhysicalPath="$(WebProjectOutputDir)"
Force="true"
/>
</Target>
<!-- ... -->
</Project>
You may also set TargetPath attribute to specify destination directory.
AfterTargets="build" is similar to "post-build event". See Target Build Order for more.
Integrate ASPX compilation into Visual Studio
One of the principles I insist on is to always try my build on a clean environment and simulate installation as if it was done by QA. Lately I've noticed that I keep falling on errors hidden deep in the aspx files. So, why not using the old and familiar aspnet_compiler.exe tool? It is located at C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 and it is quite easy to use.
As a VS add-ins freak I've started thinking on an amazing add-in that will integrate to the VS and will listen to build events and display the results at the output pane. Heck, why not add some coffee serving capabilities?
It took me about 10 minutes of googling to stumble on this blog. Mike Hadlow had a genius in its simplicity idea. Use the POST BUILD EVENT!
All I need to do is put the following line in the post build event: C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v / -p "$(ProjectDir)\"
Now, All that is left is to make the process of adding this line to each and every web project in our team to be automatic.
I have just the add-in for that :)
enter link description here
The answer from Matej was helpful for me, but I was not able to use it as-is and still get it to work for both local builds within Visual Studio and automated builds via TFS.
I had to add some extra msbuild settings. Actually, there were 2 different scenarios that I had. One project was an Web App that built into the _PublishedWebsites folder and one was an MVC Web App that did not build into the _PublishedWebsites folder.
First, add the following if it is not already in your project file:
<PropertyGroup>
<MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
For the one WITH _PublishedWebsites:
<Choose>
<When Condition="'$(BuildingInsideVisualStudio)' == true">
<PropertyGroup>
<AspNetCompilerPhysicalPath>$(ProjectDir)</AspNetCompilerPhysicalPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<AspNetCompilerPhysicalPath>$(WebProjectOutputDir)</AspNetCompilerPhysicalPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<!-- aspnet_compiler.exe needs to be run on the folder that has the aspx files and the "bin" subfolder.
When running locally, the value needs to be the project directory, which is $(ProjectDir).
When running the TFS build, the value needs to be (BuildFolder)\(ProjectName)\_PublishedWebsites\(ProjectName).
The $(AspNetCompilerPhysicalPath) will hold the correct value for both types of builds.
-->
<Message Text="Starting AspNetCompiler for $(ProjectName) at $(AspNetCompilerPhysicalPath)" Importance="high" />
<AspNetCompiler
VirtualPath="/"
PhysicalPath="$(AspNetCompilerPhysicalPath)"
TargetPath="$(AspNetCompilerPhysicalPath)\bin_precompile"
Force="true"
/>
</Target>
For the one WITHOUT _PublishedWebsites:
<Choose>
<When Condition="'$(BuildingInsideVisualStudio)' == true">
<PropertyGroup>
<AspNetCompiler_CopyFilesFirst>false</AspNetCompiler_CopyFilesFirst>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup>
<AspNetCompiler_CopyFilesFirst>true</AspNetCompiler_CopyFilesFirst>
</PropertyGroup>
<ItemGroup>
<AllOutputFiles Include="$(OutDir)\\**\*.*" />
</ItemGroup>
</Otherwise>
</Choose>
<Target Name="PrecompileWeb" AfterTargets="build" Condition="'$(MvcBuildViews)'=='true'">
<!-- aspnet_compiler.exe needs to be run on the folder that has the cshtml files and the "bin" subfolder. I could not find a setting that was appropriate for both.
When running locally, the value needs to be the project directory, which is $(ProjectDir).
When running the TFS build, there is no folder that matches both of those criteria.
So first we will copy the output into the source code folder's "bin" subfolder,
then run it against the source $(ProjectDir), the same as if we were building locally.
-->
<Message Text="Before running AspNetCompiler, copy files from $(OutDir) to $(ProjectDir)\bin" Importance="high" />
<Exec Command="( robocopy.exe /mir $(OutDir) $(ProjectDir)\bin ) ^& IF %25ERRORLEVEL%25 LEQ 1 exit 0" Condition="'$(AspNetCompiler_CopyFilesFirst)'=='true'" />
<Message Text="Starting AspNetCompiler for $(ProjectName) at $(ProjectDir)" Importance="high" />
<AspNetCompiler
VirtualPath="/"
PhysicalPath="$(ProjectDir)"
TargetPath="$(ProjectDir)\bin_precompile"
Force="true"
/>
</Target>

ASP.NET MVC 1.0 AfterBuilding Views fails on TFS Build

I've upgraded from ASP.NET MVC Beta to 1.0 and did the following changes to the MVC project (as descibed in the RC release notes):
<Project ...>
...
<MvcBuildViews>true</MvcBuildViews>
...
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
</Target>
...
</Project>
While the build runs fine on our local dev boxes, it fails under TFS 2008 Build with "Could not load type 'xxx.MvcApplication'", see below build log:
...
using "AspNetCompiler" task from assembly "Microsoft.Build.Tasks.v3.5, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".
Task "AspNetCompiler"
Command:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v temp -p D:\Builds\xxx\Continuous\TeamBuild\Sources\UI\xxx.UI.Dashboard\\..\xxx.UI.Dashboard
The "AspNetCompiler" task is using "aspnet_compiler.exe" from "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe".
Utility to precompile an ASP.NET application
Copyright (C) Microsoft Corporation. All rights reserved.
/temp/global.asax(1): error ASPPARSE: Could not load type 'xxx.UI.Dashboard.MvcApplication'.
The command exited with code 1.
Done executing task "AspNetCompiler" -- FAILED.
...
MVC 1.0 is installed on TFS and the solution compiles when built within a Visual Studio instance on the same TFS server.
How can I resolve this TFS Build issue?
Actually, there's a better solution to this problem. I've tested it with VS/TFS 2010 but it should also work with VS/TFS 2008.
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
I'm going to work with the MVC team to update their project template to to use this approach along with a custom target (rather than overriding AfterBuild).
I've published a blog post on How to Turn on Compile-time View Checking for ASP.NET MVC projects in TFS Build 2010.
The problem stems from the fact that the AspNetCompiler MSBuild task used within the AfterBuild target of an ASP.NET MVC project expects to reference the dll's in the bin folder of the Web project.
On a desktop build the bin folder is where you would expect it under your source tree.
However TFS Teambuild compiles the output of your source to a different directory on the build server. When the AspNetCompiler task starts it cannot find the bin directory to reference the required DLL and you get the exception.
Solution is to modify the AfterBuild target of the MVC Project to be as follows:
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler Condition="'$(IsDesktopBuild)' != 'false'" VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
<AspNetCompiler Condition="'$(IsDesktopBuild)' == 'false'" VirtualPath="temp" PhysicalPath="$(PublishDir)\_PublishedWebsites\$(ProjectName)" />
</Target>
This change enables you to compile Views on both the desktop, and the TFS build server.
Jim Lamb's solution didn't work for us when I built our web .csproj with
/p:UseWPP_CopyWebApplication=true;PipelineDependsOnBuild=False
because the target was being executed AfterBuild and the application has not been copied into the WebProjectOutputDir yet. (BTW, I pass those properties to the web project build cos I want the build to create a OutDir folder with only my binaries and cshtml files suitable for zipping, ie not an in-place build)
To get around this issue and honour the intent of his original target, I did the following:
<PropertyGroup>
<OnAfter_WPPCopyWebApplication>
MvcBuildViews;
</OnAfter_WPPCopyWebApplication>
</PropertyGroup>
<Target Name="MvcBuildViews" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
I assume you meant you changed the following setting in the .csproj file:
<MvcBuildViews>true</MvcBuildViews>
The setting you posted in your question shouldn't be touched.
If it works on your local machine, then obviously you can pre-build an ASP.NET MVC application.
I think you need to track down what's different between your TFS build environment and your local VS machines. Maybe it's using a different version of MsBuild or something.
Try performing both builds with verbose output and compare the two to see what's different.
We are still testing this out, but it appears that you can move the false/true from the tag set, into the property group for your DEBUG build version, you can still set it to true and MSBuild will compile (assuming MSBuild TfsBuild.proj file is setup to use something other than debug configuration). You will need to edit the csproj file using Notepad to accomplish this.
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<MvcBuildViews>true</MvcBuildViews>
....
You need to move the MVCBuildViews tag from the default property group above, to the debug configuration property group (below). Again, when we get the TFS / MSBuild setup, I'll try to post the step we added to our TFSBuild.proj file in TFS.
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<MvcBuildViews>true</MvcBuildViews>
<DebugSymbols>true</DebugSymbols>
....
This problem seems similar to the one talked about here:
http://blogs.msdn.com/aaronhallberg/archive/2007/07/02/team-build-and-web-deployment-projects.aspx
it seems the invocation of aspnet_compiler.exe fails to locate the binaries because the are not in the bin folder of the MVC project on the build machine. I haven't worked out a solution yet.
The accepted answer didn't work for me. The $(PublishDir) parameter did not point to the correct location. Instead I had to use:
<Target Name="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler Condition="'$(IsDesktopBuild)' != 'false'" VirtualPath="temp" PhysicalPath="$(ProjectDir)\..\$(ProjectName)" />
<AspNetCompiler Condition="'$(IsDesktopBuild)' == 'false'" VirtualPath="temp" PhysicalPath="$(OutDir)\_PublishedWebsites\$(ProjectName)" />
</Target>
I had some old folders in my source control that were not visible in the Solution.
You cannot pre-build an ASP.NET MVC application.

How can I deploy an ASP.NET web application using Team Build?

I have managed to install Team Foundation Server 2008 and I created a separate build server (which works because my builds are currently failing).
I have created a simple "Hello World" Web application (all is the standard Default.aspx page) and have it in TFS's source control system.
Previously, prior to TFS, I'd simply precompile my web application and xcopy the results on to a pre-created IIS Virtual directory.
Scouring Google for a while, I have yet to find a step by step guide on correctly deploying an application from TFS Source via TeamBuild to a designated test web server. I know MS Build falls into this equation, so any guidance would be helpful.
I have seen bits and pieces about deployments, with folders such as _PublishedWebSites mentioned, but have yet to find anything step by step.
I've had success using a exec task in the AfterDropBuild target in the TFSBuild.proj file.
<Target Name="AfterDropBuild>
<Exec Command="xcopy /Y /E "$(DropLocation)\\$(BuildNumber)\%(ConfigurationToBuild.FlavorToBuild)\_PublishedWebsites\MyWebsite1\*.*" "\\server\MyWebsite1\"" />
<Exec Command="xcopy /Y /E "$(DropLocation)\\$(BuildNumber)\%(ConfigurationToBuild.FlavorToBuild)\_PublishedWebsites\MyWebsite2\*.*" "\\server\MyWebsite2\"" />
</Target>
Note that the permissions need to be setup correctly for the TFS service user to access the folder on the server your are copying to.
Firstly you should be using WebDeployment projects as this will do a lot more compilation and checking of your code and markup. See here for more info.
I have 4 environments setup DV [Development], PY [Prototype], PP [Pre-Production], PD [Production] all matching branches in TFS. Each of these has also has an entry in the sln configuration manager where you can setup what projects are required to be build and the build flags.
Once that is setup correctly you can then start setting up deployment scripts. I prefer use MSbuild to deploy as it will give you a lot more fine-grained approach to deployment. MSbuild is a bit strange to start with however once you get the hang of it it's quite powerful.
My deployment script which is added to the TeamBuild config is below. Basically as you can see I do a bit of post-build cleanup before I copy to the live servers. I also use 2 MSbuild frameworks (imported at the top).
<Import Project="$(MSBuildExtensionsPath)\Microsoft\SDC Tasks - Release 2.1.3155.0\Microsoft.Sdc.Common.tasks"/>
<Import Project="$(MSBuildExtensionsPath)\FreeToDev\MSBuild Tasks Suite 3.5\FreeToDev.MSBuild.tasks"/>
<PropertyGroup>
<InetpubFolder>\\PathToInetPub</InetpubFolder>
<AppFolder>AppFolder</AppFolder>
<AppFolderPath>$(InetpubFolder)$(AppFolder)</AppFolderPath>
<WebDeployName>WebDeployProjectName</WebDeployName>
<Debug>0</Debug>
<AppConfiguration>DV</AppConfiguration>
</PropertyGroup>
<Target Name="AfterDropBuild">
<Message Text="Begin Release to $(AppConfiguration) Webserver" />
<Message Text="DropLocation = $(DropLocation)" />
<CallTarget Targets="PostBuildCleanUp" />
<CallTarget Targets="DeployApp" />
</Target>
<Target Name="DeployApp">
<GetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)">
<Output TaskParameter="DropLocation" PropertyName="DropLocation"></Output>
</GetBuildProperties>
<PropertyGroup>
<CodeDropLocation>$(DropLocation)\$(AppConfiguration) Release</CodeDropLocation>
</PropertyGroup>
<ItemGroup>
<AppFilesToDelete Include="$(AppFolderPath)\**\*.*" Exclude="$(AppFolderPath)\Library\*.*;$(AppFolderPath)\App_Offline.htm;$(AppFolderPath)\jobs\**\*.*" />
</ItemGroup>
<ItemGroup>
<FilesToDeploy Include="$(CodeDropLocation)\$(AppFolder)\**\*.*" Exclude="" />
</ItemGroup>
<Copy SourceFiles="$(CodeDropLocation)\$(AppFolder)\App_Offline[RemoveToActivate].htm" DestinationFiles="$(AppFolderPath)\App_Offline.htm" OverwriteReadOnlyFiles="true"/>
<Message Text="Deleting files in $(AppFolderPath)" />
<Microsoft.Sdc.Tasks.File.DeleteFiles Files="#(AppFilesToDelete)" Force="true" Condition="$(Debug)==0" />
<Message Text="Copy $(CodeDropLocation)\$(AppFolder) to $(AppFolderPath)" />
<Copy Condition="$(Debug)==0" SourceFiles="#(FilesToDeploy)" DestinationFiles="#(FilesToDeploy->'$(AppFolderPath)\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true"/>
<Message Text="Deploy to $(AppConfiguration) Completed" />
<Microsoft.Sdc.Tasks.File.DeleteFiles Files="$(AppFolderPath)\App_Offline.htm" Force="true" />
<OnError ExecuteTargets="ErrorHandler" />
</Target>
<Target Name="ErrorHandler">
<Message Text="Error encountered!!" />
</Target>
<Target Name="PostBuildCleanUp">
<GetBuildProperties TeamFoundationServerUrl="$(TeamFoundationServerUrl)" BuildUri="$(BuildUri)">
<Output TaskParameter="DropLocation" PropertyName="DropLocation"></Output>
</GetBuildProperties>
<PropertyGroup>
<CodeDropLocation>$(DropLocation)\$(AppConfiguration) Release</CodeDropLocation>
</PropertyGroup>
<ItemGroup>
<PostBuildCleanUpFilesToDelete Include="$(CodeDropLocation)\*.*;$(CodeDropLocation)\bin\*.xml;$(CodeDropLocation)\bin\*.pdb"/>
</ItemGroup>
<RemoveDir Directories="$(CodeDropLocation)\_PublishedWebsites\Web" />
<Microsoft.Sdc.Tasks.File.DeleteFiles Files="#(PostBuildCleanUpFilesToDelete)" Force="true">
<Output TaskParameter="DeletedFiles" ItemName="FilesThatWereDeleted" />
</Microsoft.Sdc.Tasks.File.DeleteFiles>
<Message Text="The files that were removed were #(FilesThatWereDeleted)" />
<FTDFolder TaskAction="Move" Path="$(CodeDropLocation)\_PublishedWebsites\$(WebDeployName)" TargetPath="$(CodeDropLocation)\$(AppFolder)"/>
<RemoveDir Directories="$(CodeDropLocation)\_PublishedWebsites" />
<RemoveDir Directories="$(CodeDropLocation)\$(AppFolder)\WebDeploy" />
<OnError ExecuteTargets="ErrorHandler" />
</Target>
Obviously you will need to modify to your system setup. Also it clears down the target folder before it starts to copy the new build accross. This is to make sure they system is clean but obviously you will need to add anything that you need to keep to the ExcludedFiles list.
I also have a folder for each environment in the main application project. This holds the web.config replacements (another feature of WebDeployment projects) and any other environement specifc files.
It will be a long process to get it working correctly but hopefully this will get you started!! (Obviously if you choose this apporach!)
This can be done via the build scripts directly, the Vertigo Software guys usually are the best source of info for a lot of TFS questions like this...unfortunately their blog posts don't usually rank that high on google. This one's by Jeff Atwood, one of the creators of this site:
Copying Web Files After a Team Build

Resources