Publish web application from MSBuild Script using VS2010 targets resets working directory - visual-studio-2010

I am trying to automatically publish and deploy my .Net 4 web application automatically from a build script to be run by our continuous integration server. I am using the new _WPPCopyWebApplication target from VS2010 to perform the publish, however it appears to reset the current working directory of the msbuild project to c:\ this causes my prebuild steps to fail as they have relative paths to some external tools. The task I am running from our master.build file is as follows:
<Target Name="PublishWeb">
<MSBuild
Projects="$(ProjectPath)"
Targets="ResolveReferences;_WPPCopyWebApplication"
Properties="WebProjectOutputDir=$(DeployPath);OutDir=$(TempOutputFolder)$(WebOutputFolder)\;OutputPath=$(ProjectPath)\bin\Debug;" />
</Target>
This does not happen when using the legacy _CopyWebApplication. Does anyone have any idea how to resolve this problem?

Two possibilities come to mind:
Use the Exec task to call msbuild.exe, and supply a specific working directory.
Your pre-build steps are evaluated by MSBuild and can reference any MSBuild property, so make your paths relative to something specific, like $(MSBuildProjectDirectory), or $(MSBuildThisFileDirectory), instead of just relative to the current directory.

Related

Build Wix installer Project in Teamcity 9.1, but how to set the `WixToolPath` in build machine?

I'm using Win10 64bit OS, with Wix3.11RC Toolset installed. My VS2017 have created a Wix v3 installer Project. Our team is using TeamCity9.1 as the CI tool.
Now I want to make the Build Agent in TeamCity to support wixproj build without touch CI server settings(I don't have privilege ). I basically follow some tutorials to checked in all necessary Wix build files(the wix Bin folder, and the wix.targets ) which is put in a relative path to the source code, now I'm blocked with the path issue in editing .wixproj file, the official doc said:
http://wixtoolset.org/documentation/manual/v3/msbuild/daily_builds.html
<PropertyGroup>
<WixToolPath>$(SourceCodeControlRoot)\wix\[[Version]]\</WixToolPath>
<WixTargetsPath>$(WixToolPath)Wix.targets</WixTargetsPath>
<WixTasksPath>$(WixToolPath)wixtasks.dll</WixTasksPath>
</PropertyGroup>
And this is mine:
<PropertyGroup>
<WixToolPath>..\..\wix\3.11\</WixToolPath>
<WixTargetsPath>$(WixToolPath)targetsFile\v3.x\wix.targets</WixTargetsPath>
<WixTasksPath>$(WixToolPath)wixtasks.dll</WixTasksPath>
</PropertyGroup>
The reason I'm using the relative path for WixToolPath is the $(SourceCodeControlRoot) was resolved as D:\ here, but actually the source code will be checked out by CI server and put under a random folder like D:\ABC\f14c7929aa63f1fc. By my configuration, the local build even can't go through, the build error indicates the WixTasksPath had been resolved to a non-existed path: C:\Program Files (x86)\MSBuild\Microsoft\WiX\v3.x\..\..\wix\3.11\wixtasks.dll
So how can I achieve? thanks!
One of the approaches you can try is to change the path in the file to the absolute path using TeamCity-provided references before invoking the tool. In TeamCity settings you can reference the checkout directory path as %system.teamcity.build.checkoutDir% or use ${teamcity.build.checkoutDir} within MSBuild step if run as MSBuild build step.
You can do the replacement in the first build step or just use TeamCity file content replacer to change the old value to new one.
just use
<WixTasksPath>wixtasks.dll</WixTasksPath>
this worked for me.

Running post deployment script after Web Deploy

I have the following problem and I'm surprised that I can't find any straightforward solution on SO or MSDN.
I have existing *.pubxml profiles in several of my web applications and I would like to execute post deployment script - powershell script - which reorganizes WebSite and its child applications slightly.
I'm not usign Web Deployment Package - just Web Deploy.
The script is deployed successfully but the problem is - how should I execute it automatically after deployment?
I have two scenarios:
Execute by simply "Publish..." from Visual Studio.
Execute as part of TFS Build definition (TFS 2013).
You can try to define a “Target” by MSBuild to achieve your requirement.
For the first scenario:
The Visual Studio build process is defined by a series of MSBuild .targets files that are imported into your project file. One of these imported files, Microsoft.Common.targets. This file contains a set of predefined empty targets that are called before and after some of the major targets in the build process.
So you can define a "Target" element whose "AfterTarget" attribute's value is set to "MSDeployPublish":
<Target Name="CustomPostPublishActions" AfterTargets="MSDeployPublish" >
<Exec Command="..\PostDeploymentScript.sp1 " />
</Target>
For the second scenario:
You can add a PowerShell build task as MrHinsh`s suggestion.
You should switch to deploying from Build & Release only in VSTS/TFS.
You can then add a PowerShell build task and either point at a script or use Inline if it's short. If it is a script that you use in many builds you might want to write your own build task.

TFS Build - How to deploy to Multiple locations

How to deploy (copy the application files) to multiple locations when TFS build is executed.
See the picture when ever build is initiated I am copying to a location, I wanted to give multiple location in MSBuild Arguments.
MSBuild Arguments : /p:DeployPath=\\ServerName\C$\Inetpub\wwwroot\ApplicationName
Add another CopyDirectory activity to your build process template XAML.
<mtbwa:CopyDirectory DisplayName="Drop Files to Drop Location" Source="[BinariesDirectory]" Destination="[DropLocation]" />
Or, use MSBuild Copy task in the last scipt being run in the build (AKA post-build script).

TeamCity - problem with Publish on ASP.net site

I am trying to configure TeamCity 5.0 to run "Publish" target on one of my projects.
When I load the solution in VS 2008 and click publish on the project the website is being build nicely - files on server appearing by themselves etc. Yet when I run the sln file via TeamCity Sln2008 runner the TeamCity returns:
[Project "Portal.csproj" (Publish target(s)):] Skipping unpublishable project.
Has anyone had the same problem?
Filip
You could create your own simple build file. For example:
<Project DefaultTargets="Build" ToolsVersion="3.5" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
<PackageFolder>C:\Builds\AppServer\Actual</PackageFolder>
</PropertyGroup>
<Target Name="Build" DependsOnTargets="BeforeBuild">
<MSBuild Projects="TeamWork-AppServer.sln"
Targets="Rebuild"
Properties="Configuration=Debug;OutDir=$(PackageFolder)\;"></MSBuild>
</Target>
</Project>
Or you can use VS 2008 Web Deployment Project. Here is a great turtorial.
If it is a WebProject you can use the Microsoft.WebApplication.targets. Unless you have installed the windows SDK on your build agent you will need to copy the targets file into your source control and reference it from your web project by adding:
<Import Project="{path to your tools}\Microsoft.WebApplication.targets" />
You can find the targets file here (depending on your os):
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v9.0\WebApplications
Now you just need to update your msbuild task to reference the right targets:
<MSBuild Projects="{path to your web project file}"
Targets="Build;ResolveReferences;_CopyWebApplication"
Properties="Configuration=Release;Architecture=Any;WebProjectOutputDir={your web root};OutDir={your web root}\bin\" />
Here is how I modified the .csproj file for an ASP.NET MVC project to deploy via TeamCity 5.1.2. In the .csproj file, replace the AfterBuild target with this XML (If there are already commands in your existing AfterBuild, you will have to merge them into these targets):
<PropertyGroup>
<DeployTarget>0</DeployTarget>
<PublishTarget>0</PublishTarget>
<PublishFolder>..\Deployment\YourWebsiteName</PublishFolder>
</PropertyGroup>
<Target Name="PublishProperties">
<CreateProperty Value="$(PublishFolder)">
<Output TaskParameter="Value" PropertyName="WebProjectOutputDir"/>
</CreateProperty>
<CreateProperty Value="$(PublishFolder)\bin\">
<Output TaskParameter="Value" PropertyName="OutDir"/>
</CreateProperty>
</Target>
<Target Name="WebPublish" DependsOnTargets="BeforeBuild;PublishProperties">
<RemoveDir Directories="$(PublishFolder)"
ContinueOnError="true" />
<CallTarget Targets="ResolveReferences;_CopyWebApplication" />
</Target>
<Target Name="Deploy" DependsOnTargets="WebPublish">
<CreateProperty Value="Path\To\Your\Server" Condition="$(DeployFolder) == ''">
<Output TaskParameter="Value" PropertyName="DeployFolder"/>
</CreateProperty>
<RemoveDir Directories="$(DeployFolder)" Condition="$(CleanDeploy) == 1" />
<ItemGroup>
<DeploymentFiles Include="$(PublishFolder)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(DeploymentFiles)"
DestinationFolder="$(DeployFolder)\%(RecursiveDir)" />
</Target>
<Target Name="AfterBuild">
<CallTarget Targets="WebPublish" Condition="$(PublishTarget) == 1" />
<CallTarget Targets="Deploy" Condition="$(DeployTarget) == 1" />
</Target>
This script uses the $(PublishTarget) and $(DeployTarget) properties to trigger additional steps after your project is built. The PropertyGroup at the beginning sets the default values to 0, so the extra targets are not run. You can override the default in TeamCity by going to the Properties and Environment Variables page of your build configuration and adding System Properties names "PublishTarget" and "DeployTarget" and setting their value to 1.
The Publish target contains most of the magic. This makes a call to the Visual Studio _CopyWebApplication target to output the website to the PublishFolder. By default the publish folder is "..\Deployment\YourWebsiteName" relative to the project file, but this can also be overridden with a System Property. The Deploy target takes the files output by the Publish target and copies them to the DeployFolder. DeployFolder can be set with a System Property in TeamCity or you can replace the "Path\To\Your\Server" path in the Deploy target.
You could also skip the extra Deploy step by simply setting the PublishFolder to whatever your deployment destination is. This script depends on the "Microsoft.WebApplication.Build.Tasks.Dll" and "Microsoft.WebApplication.targets" files installed by Visual Studio, but you can simply copy the files from your developer workstation to the build server. The default location is "C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\WebApplications".
I have this same problem, here's what I've tried:
I have a solution file in Visual Studio 2010, committed to a Mercurial repository.
I have setup an FTP server for the root directory of the site to publish to, and publishing from within Visual Studio 2010 locally works nicely, it connects and uploads everything as expected, and the website works.
Now, I wanted to automate this on every push to the central Mercurial repository, and since I'm using TeamCity, I discovered that the field to specify the Target of the build, usually "Rebuild" can also take "Publish", so I specified "Rebuild;Publish", as per the documentation and help.
I have verified that after publishing in Visual Studio, and committing new files, a file named ProjectName.Publish.xml is accompanying my ProjectName.csproj file, and this file is pulled down into the server directory when TeamCity builds.
Yet, no publishing is done, and when I check the build log, it says:
[19:01:02]: [Project "Test.sln" (Rebuild;Publish target(s)):] Project "Test.UI.Web.csproj" (Publish target(s)):
[19:01:02]: [Project "Test.UI.Web.csproj" (Publish target(s)):] Skipping unpublishable project.
Exactly as the question here says.
Note that this is a development site, publishing just so that we can let more people test changes, so don't get into a discussion of whether this is actually a good idea or not.
Note: I do not care in which way the files are published, I just need the single TeamCity build-step to actually do it, so if anyone got a MSBuild-like solution that just sidesteps TeamCity, then I would be satisfied
Have you tried to execute Visual Studio directly, rather than relying on MSBuild to publish the project directly. MSBuild can't execute certain kinds of projects. I had a similar problem with getting MSI's built from within Team City.
I'm taking a guess at the exact commandline settings to this, since I don't know your exact setup.
<PropertyGroup>
<buildconfiguration>Release</buildconfiguration>
<DevEnv>C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.com</DevEnv>
</PropertyGroup>
<Exec Command="%22$(DevEnv)%22 /build $(buildconfiguration) $(teamcity_build_checkoutDir)\Test.sln /project Test.UI.Web.csproj"/>
If you're using the Team City solution runner as your build runner, you'll have to switch to MSBuild.
If you want to stay with the Team City runner, you could always try adding a project to your solution that will be the last one built, (or do it on the project that currently gets built last), and do the spawning trick as a post-build command line on the project.
Can TeamCity publish a Web project using the sln2008 build runner
Can TeamCity publish a Web project using the sln2008 build runner?
What type of project are you trying to publish?
http://social.msdn.microsoft.com/forums/en-US/msbuild/thread/7ec0d942-6354-41c3-9c97-7e7d1f461c29
Taken from above link:
What I discovered is that "Shared-addins" are not publishable
and are distinct and different from document and application level
VSTO addins, which are deployable.
When I rebuilt my application as an application level
VSTO addin, the publish option was available.
http://www.automise.com/Default.aspx?tabid=53&aft=9813
Taken from above link:
Assuming you're using Visual Studio 2008, we're unable to execute the web site
publish feature from FinalBuilder as it's partially implemented by the VS IDE.
You'll need to use to the MSBuild action to compile the application and then
use one of the other actions (FTP, File Copy, etc) in FinalBuilder to perform
the deployment. Visual Studio 2010 has fixed this problem by performing the
entire publish using MSBuild, see this post for more info:
http://www.finalbuilder.com/forums....&afv=topic
Two threads that might help
http://devnet.jetbrains.net/thread/280420;jsessionid=5E8948AE810FFFF251996D85E7EB3FE3
Visual Studio. Publish project from command line
For anyone using Web Application Projects in VS2010, I managed to get TeamCity to package the deliverables and then Web Deploy the package after successfully building the solution.
With a little tweaking, this had the same effect as hitting the 'Publish' button in VS.
My solution has a handful of projects, 1 of which is an ASP.NET MVC Web Application project. I build the solution, package the web app project, and msdeploy the package in 3 steps. I haven't figured out a (better|shorter|simpler|more elegant) way to do this.
I don't have VS installed on my TeamCity server, so I needed to grab both C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\Web and C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.0\Web Applications and put them both in the same spot on the TeamCity server (the second depends on the first). If you're working w/x64 machines, I'd grab them from both Program Files (x86) and Program Files. You also need to have Web Deploy installed on your machine and (I believe) IIS Management Service (i.e., something listening on https://yourservername:8172/MsDeploy.axd)
There are 3 build steps:
Visusal Studio (sln), Target=Rebuild, Configuration=Debug
MSBuild WebProject.csproj, Targets=Package Commandline=/p:PackageLocation=%teamcity.build.checkoutDir%\Debug.zip /p:Configuration=Debug
Commandline, Executable=%teamcity.build.checkoutDir%\Debug.deploy.cmd, Parameters=
/Y "-setParam:'IIS Web Application Name'='Default Web Site/PreCreatedAppInIis'"
In that last step, 'IIS Web Application Name' is an actual parameter name, don't change it. It's value can either be something like 'Default Web Site' or whatever you named your website in IIS and/or it can be an IIS application path below it. If the application doesn't exist, you may run into errors about the app pool not being configured correctly to host the application. Rather than investigate it, I just created an application in the appropriate app pool. In my case, I'm targeting ASP.NET 4.0 x64 where the default app pool is ASP.NET 2.0 x64.

Calling batch/script files from VC6/VC2005/VC2008 project files

Is there a way to invoke an external script or batch file from VC6 (and later) project files?
I have a background process that I need to kill before attempting to build certain projects (DLLS, executables) and haven't found a way to successfully do so from the project itself. I'd like simply to call a batch file with a taskkill command in it.
(Yes, I could run the batch file from a command line before building the projects, but I don't always remember to do so and having it done automatically would be more convenient and less irritating for the whole development team.)
You can create a utility project (configuration type: Utility in the project property pages) that has a post build event. You then call the batch file from that Post-Build event. If I remember correctly, utility configuration appeared in VS2005. But I believe the same can be achieved with another type of configuration on VC6.
Here is an example of a setup (this is the text of the Command Line property of the Post-Build Event):
set solutionDir=$(SolutionDir)
set platformName=$(PlatformName)
set configurationName=$(ConfigurationName)
call $(SolutionDir)PostBuild.bat
As you can see, you have all the flexibility of customizing the batch environment based on VisualStudio macros.
If you want to have this batch file called every time you build, add a dependency to the requiring project (your main executable or dll project for example). You can add your batch file to the solution items for convenient access (right-click on the solution and select Add -> Existing Item...).
You can even invoke the build command on this utility project to force the execution of the batch file.
At work we have a similar setup to start our unit tests each time a build is triggered.
You could invoke it from a custom build step or a build event.
At least for C# in Visual Studio 2008, you can open the project file and find within the file the following comment:
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
Uncomment the one that works best for you, in this case the "BeforeBuild" item. Then substitute your batch file for the one I have here:
<Target Name="BeforeBuild">
<Exec Command="MyBatchFile.bat" />
</Target>
That's all there is to it; whenever you build that project, this will take place each and every time.
That said, I do not know if this works the same for VS 2005 or, especially, VC6. YMMV!

Resources