I am hoping to be able to use MSBuild to capture a subtree of files produced during the build of a project using Microsoft.NET.Sdk.Web and include them in deployment. So far, I have found that if I simply create the files inside the project folder before deployment, then it works but only for certain filetypes. DLLs, for instance, are excluded, presumably assumed to be non-content items. I have been poking around how the deployment stuff works, and have found the <ResolvedFileToPublish> element that I can put into <ItemGroup>, but I haven't figured out how it might be possible to employ this with wildcards. Specifically, I have a post-build step that places files into a folder deployment within the project, and I want all files in that subtree to be included in the package that is produced by /p:DeployOnBuild=true. How can I tack my files onto the deployment stage so that they're included in the ZIP even if they don't look like content items?
I have found a solution, in the form of adding a new <Task> set to run immediately after the internal tasks which collect files for publishing. This is not suitable for a long-term solution, since it ties to internal state, but this is a temporary fix and as such I think it's alright.
By adding this to the .csproj:
<Target Name="__CopyDeploymentToPublish" AfterTargets="_CopyResolvedFilesToPublishAlways">
<Exec Command="PowerShell.exe -Version 3.0 -ExecutionPolicy Unrestricted $(SolutionDir)deploy_webapp.ps1 -Source $(SolutionDir)src\IQ.Auth.OAuth2.Web -Target $(PublishDir)" />
</Target>
...my PowerShell script runs right after the standard deployment logic aggregates the files it intends to package up. I can at that point do whatever I want to the files and the way they're left is what'll end up in the ZIP file.
I'm harvesting a directory for my Visual Studio solution.
It works on my local system so far probably because the project build order is being respected.
When I run the installer on a build server it finds the right directory but it has not been created at the time of building the setup file. It throws a HEAT5052 error saying The directory 'a:\b\c' could not be found.
Is there any way to "wait" until or to execute the heat command after all project references are built?
OK so I've spent hours to figure out how to fire Heat AFTER all references are resloved. I only found solutions for the <PreBuildEvent> and <PostBuildEvent> using the Heat command line and the BeforeBuild and AfterBuild targets.
So I found all kind of targets inside the wix2010.targets file located in my
Program files (x86)\MSBuild\Microsoft\Wix\ folder. It contains a target called AfterResolveReferences and it does exactly that. So here's my code I ended up with (in case someone is interested):
<Target Name="AfterResolveReferences">
<HeatDirectory
ToolPath="$(WixToolPath)"
OutputFile="Product.Binaries.wxs"
SuppressFragments="$(HarvestDirectorySuppressFragments)"
Transforms="Filter.xslt"
Directory="$(HarvestFolder)"
DirectoryRefId="MY_FOLDER"
ComponentGroupName="Binaries"
GenerateGuidsNow="true"
SuppressRootDirectory="true"
SuppressRegistry="true"
PreprocessorVariable="var.App.TargetDir">
</HeatDirectory>
</Target>
I had the same problem and it was solved by combining the accepted answer and this answer to ensure that my post build event, which was copying files, always runs:
<RunPostBuildEvent>Always</RunPostBuildEvent>
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
Also, my build server was using the MSBuild command line, and I used this answer to locate my local MSBuild.exe so I could test my changes locally without having to push to the build server.
I'm using MsBuild to build and publish my project (along with CruiseControl.Net). I have set everything up and it works great but the problem is it's overwriting all my existing files in the deployed folder(and the folder contains user data, i could do an xcopy after the build/publish but the user data is a few gigs and that would be too much disk activity on each automated build).
So what I would like to do is use a "Replace only Existing files" option instead of removing everything from the folder. I get this option in Visual Studio 2010 when publishing, you can either "Replace Exiting Files" or "Delete All Files First", how to do this using the msbuild command parameters.
<msbuild>
<executable>C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
<workingDirectory>C:\CCnet\dmisr-web_workingdir\MAKANI</workingDirectory>
<projectFile>MAKANI.sln</projectFile >
<buildArgs>/noconsolelogger /v:quiet /p:Configuration=Staging /p:DeployOnBuild=true /p:DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder /p:_PackageTempDir="c:\dMisr\Web - Deployed" /p:AutoParameterizationWebConfigConnectionStrings=false</buildArgs>
<targets>ReBuild</targets >
<timeout>600</timeout >
</msbuild>
This answer may help
How do I keep MSDeploy from deleting extra folders in my project?
Looks like you may just need to supply an extra property to msbuild.
SkipExtraFilesOnServer=True
/p:SkipExtraFilesOnServer=true is still removing other files for me when using these build arguments
/p:DeployOnBuild=true;DeployTarget=PipelinePreDeployCopyAllFilesToOneFolder;_PackageTempDir=\\Network\Share\code /p:AutoParameterizationWebConfigConnectionStrings=false /p:SkipExtraFilesOnServer=true
I do not seem to have the ability to comment. Hence providing my comments in the answer section.
As part of a build process .. I would like to block the build until a file gets created (exists) remotely at an ftp location, after which I would continue the build. (Preferably with somekind of time out limit).
Suggestions?
Is this even possible using only the standard msbuild task and/or extensionPack/communitytask?
Your best bet is to build a small custom exe (you can even compile it as a build step) that polls for the file you are looking for. Then you use the PreBuild target, or a custom target in a pre-build step to verify that the file exists.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="WaitOnFTP">
<Exec Command="MyFTPWaiter.exe"/>
</Target>
</Project>
Other more MSBuild oriented suggestions are to remake that exe as a custom task, or even an inline task in MSBuild 4.0.
FWIW, I've encountered a similar solution done by a peer who didn't want large binaries used by integration tests in version control and he required the use of a custom downloader in the build to get the files from a SMB share. It worked well enough.
Custom Tasks
Inline Tasks
I am trying to use MSBuild to build a solution with a specified target platform (I need both binaries, x86 and x64). This is how I tried it:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>MsBuild SolutionPath\Solution.sln /t:Rebuild /p:Configuration=Release /p:Platform="x86"
However the build always fails if the platform is different from "Any CPU". What am I doing wrong?
This is the while output MSBuild prints:
C:\WINDOWS\Microsoft.NET\Framework\v3.5>MsBuild
SolutionPath\Solution.sln /t:Rebuild
/p:Configuration=Release
/p:Platform="x86" Microsoft (R) Build
Engine Version 3.5.30729.1 [Microsoft
.NET Framework, Version
2.0.50727.3082] Copyright (C) Microsoft Corporation 2007. All rights
reserved.
Build started 1.7.2010 8:28:10.
Project "SolutionPath\Solution.sln" on
node 0 (Rebuild targe t(s)).
SolutionPath\Solution.sln : error
MSB4126: The specified sol ution
configuration "Release|x86" is
invalid. Please specify a valid
solution c onfiguration using the
Configuration and Platform properties
(e.g. MSBuild.exe Solution.sln
/p:Configuration=Debug
/p:Platform="Any CPU") or leave those
prope rties blank to use the default
solution configuration. Done Building
Project "SolutionPath\Solution.sln"
(Rebuild t arget(s)) -- FAILED.
Build FAILED.
"SolutionPath\Solution.sln" (Rebuild
target) (1) ->
(ValidateSolutionConfiguration target)
-> SolutionPath\Solution.sln : error MSB4126: The specified s olution
configuration "Release|x86" is
invalid. Please specify a valid
solution configuration using the
Configuration and Platform properties
(e.g. MSBuild.ex e Solution.sln
/p:Configuration=Debug
/p:Platform="Any CPU") or leave those
pro perties blank to use the default
solution configuration.
0 Warning(s)
1 Error(s)
Time Elapsed 00:00:00.03
If I try to build it for x86/x64 with devenv it works perfectly, however I am trying to set up a build server without installing all the necessary versions of Visual Studio. By the way, if there is a better free tool (that supports .NET framework 4) out there, I'd love to hear about it.
In MSBuild or Teamcity use command line
MSBuild yourproject.sln /property:Configuration=Release /property:Platform=x64
or use shorter form:
MSBuild yourproject.sln /p:Configuration=Release /p:Platform=x64
However you need to set up platform in your project anyway, see the answer by Julien Hoarau.
If you want to build your solution for x86 and x64, your solution must be configured for both platforms. Actually you just have an Any CPU configuration.
How to check the available configuration for a project
To check the available configuration for a given project, open the project file (*.csproj for example) and look for a PropertyGroup with the right Condition.
If you want to build in Release mode for x86, you must have something like this in your project file:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
...
</PropertyGroup>
How to create and edit the configuration in Visual Studio
(source: microsoft.com)
(source: msdn.com)
(source: msdn.com)
How to create and edit the configuration (on MSDN)
If you're trying to do this from the command line, you may be encountering an issue where a machine-wide environment variable 'Platform' is being set for you and working against you. I can reproduce this if I use the VS2012 Command window instead of a regular windows Command window.
At the command prompt type:
set platform
In a VS2012 Command window, I have a value of 'X64' preset. That seems to interfere with whatever is in my solution file.
In a regular Command window, the 'set' command results in a "variable not defined" message...which is good.
If the result of your 'set' command above returns no environment variable value, you should be good to go.
Hopefully this helps someone out there.
For platform I was specifying "Any CPU", changed it to "AnyCPU" and that fixed the problem.
msbuild C:\Users\Project\Project.publishproj /p:Platform="AnyCPU" /p:DeployOnBuild=true /p:PublishProfile=local /p:Configuration=Debug
If you look at your .csproj file you'll see the correct platform name to use.
For VS2017 and 2019... with the modern core library SDK project files, the platform can be changed during the build process. Here's an example to change to the anycpu platform, just before the built-in CoreCompile task runs:
<Project Sdk="Microsoft.NET.Sdk" >
<Target Name="SwitchToAnyCpu" BeforeTargets="CoreCompile" >
<Message Text="Current Platform=$(Platform)" />
<Message Text="Current PlatformTarget=$(PlatformName)" />
<PropertyGroup>
<Platform>anycpu</Platform>
<PlatformTarget>anycpu</PlatformTarget>
</PropertyGroup>
<Message Text="New Platform=$(Platform)" />
<Message Text="New PlatformTarget=$(PlatformTarget)" />
</Target>
</Project>
In my case, I'm building an FPGA with BeforeTargets and AfterTargets tasks, but compiling a C# app in the main CoreCompile. (partly as I may want some sort of command-line app, and partly because I could not figure out how to omit or override CoreCompile)
To build for multiple, concurrent binaries such as x86 and x64: either a separate, manual build task would be needed or two separate project files with the respective <PlatformTarget>x86</PlatformTarget> and <PlatformTarget>x64</PlatformTarget> settings in the example, above.
When you define different build configurations in your visual studio solution for your projects using a tool like ConfigurationTransform, you may want your Teamcity build, to build you a specified build configuration. You may have build configurations e.g., Debug, Release, Dev, UAT, Prod etc defined. This means, you will have MSBuild Configuration transformation setup for the different configurations. These different configurations are usually used when you have different configurations, e.g. different database connection strings, for the different environment. This is very common because you would have a different database for your production environment from your playground development environment.
They say a picture is worth a thousand words, please see the image below how you would specify multiple build configurations in Teamcity.
In the commandline input text box, specify as below
/p:OutputPath=Publish;Configuration=Dev
Here, I have specified two commandline build configurations/arguments OutputPath and build Configuration with values Publish and Dev respectively, but it could have been, UAT or Prod configuration. If you want more, simply separate them by semi-colon,;
There is an odd case I got in VS2017, about the space between ‘Any’ and 'CPU'.
this is not about using command prompt.
If you have a build project file, which could call other solution files. You can try to add the space between Any and CPU, like this (the Platform property value):
<MSBuild Projects="#(SolutionToBuild2)" Properties ="Configuration=$(ProjectConfiguration);Platform=Any CPU;Rerun=$(MsBuildReRun);" />
Before I fix this build issue, it is like this (ProjectPlatform is a global variable, was set to 'AnyCPU'):
<MSBuild Projects="#(SolutionToBuild1)" Properties ="Configuration=$(ProjectConfiguration);Platform=$(ProjectPlatform);Rerun=$(MsBuildReRun);" />
Also, we have a lot projects being called using $ (ProjectPlatform), which is 'AnyCPU' and work fine. If we open proj file, we can see lines liket this and it make sense.
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
So my conclusion is,
'AnyCPU' works for calling project files, but not for calling solution files,
for calling solution files, using 'Any CPU' (add the space.)
For now, I am not sure if it is a bug of VS project file or MSBuild.
I am using VS2017 with VS2017 build tools installed.
In Visual Studio 2019, version 16.8.4, you can just add
<Prefer32Bit>false</Prefer32Bit>