MSBuild not publishing dll.config of dependency for ClickOnce - msbuild

My C# projectA published via ClickOnce depends on projectB. I need the projectB.dll.config file for projectA to work. While MSBuild copies over projectB.dll.config to projectA/bin/ConfigXY correctly, it is not published. VisualStudio (2017) doesn't even show the file in Application->Publish->Application Files.
As a workaround, I added this to A.csproj:
<Content Include="..\projectB\bin\Release\projectB.dll.config">
<Link>projectB.dll.config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Now VS shows the file in the "Application Files" list, but this of course works only for the Release build config. Since I have lots of configs in project A that map to different configs in B, I cannot simple use $(Configuration) in the path.
I have found some suggestions to include ..\**\*.dll.config, but that seems dangerous, as when both the Debug and Release folder exist (from a previous build), I might end up with the wrong one.
What's the right way to do this?

I’d like to post this as a comment, but due to the limitations, I post it as an answer and I am sorry for that.
I did some tests, and it seems, to include the project.dll.config file to be published(shown in Application > Publish > Application Files), we need to include this file to the projectA.
I guess you mean you want to use “..\XXX\XXX\Release\projectB.dll.config” path for Release build and use ““..\XXX\XXX\Debug\projectB.dll.config” path for Debug build without using $(Configuration) right?
Generally, MSBuild uses $(configuration) to switch the configuration mode, if it is not available for you, to my knowledge, from MSBuild side, it is hard or not possible to switch/match the configuration mode.

Related

MSBuild task does not build solution file

I have a project file that should build another solution. I tried using the MSBuild task for this, like this:
<MSBuild Projects="MySolution.sln" Properties="Configuration=$(Configuration)"/>
I tried a lot of variants, like supplying hardcoded configuration, target Rebuild and so on. Building reports an error when I pass a wrong solution name, non-existing configuration or target and so on, so it definitely loads the solution and the project files. It exits relatively fast though and produces no output. According to documentation and examples, this should work though. I also tried passing an ItemGroup for the project, including project-specific properties as suggested by examples or in MSBuild - How to build a .NET solution file (in an XML task script) from pre-written command line commands , but that does not work either. It runs without error but no output.
When passing a list of project files instead (or a single project file), it builds correctly, but the problem is that dependencies between the projects are not properly resolved. At the end, I have to supply all project files in the solution and add them to the list, which is what I want to avoid.
So, why does solution building not work, even though it should? What is wrong here?
Is this a .net project? If so you probably need to pass in a platform as well as a configuration.
<MSBuild
Projects="MySolution.sln"
Targets="build"
Properties="Configuration=$(Configuration);Platform=$(Platform)" />
If the project just contains web sites and libraries then the platform should be Any CPU if your solution just contains executables then x86 or x64 or if it's a mixture of different types of platform then you can use mixed platforms
To check what are available open the solution in Visual Studio, right click on the solution in solution explorer and select "Configuration Manager" you'll then have a drop down for "Active Solution Platforms"

Exclude folder when building from VSO to Azure website

I am trying to exclude certain files/folders from deployment of a web project in Visual Studio Online to an Azure website.
The web project has a Content folder with CSS, JS, build scripts and so on, which are only necessary for development, once deployed to Azure the CSS and JS is loaded from a CDN. Currently the build from VSO is copying all those files to the webroot in Azure, which is unnecessary and a potential security issue in case of the build scripts.
Now I know this can be prevented by setting the build action of a file to None, but this a very tedious solution because there is a lot of development going on, new files get added all the time and it is easy to forget this setting.
First I tried setting the Content folder to Cloaked in the build definitions source settings, but this only causes VSO to not download this folder on build, msbuild will still complain that those files are missing.
Is there a way to tell msbuild to ignore the whole Content folder? I already tried adding /p:ExcludeFoldersFromDeployment="Content" as a msbuild argument in the build definition, and also tried the solutions in here How to get Visual Studio 'Publish' functionality to include files from post build event?, but nothing is working.
I was studying msbuild log files and came up with a solution that is good enough for us to work with.
The first thing I learned was that I cannot prevent msbuild from copying files with build action Content to the output directory, at least not without changing the Microsoft.WebApplication.targets file, which I didn't want to do and am not even sure is possible with VSO build.
Anyway because of this we cannot set the source settings of our Content folder to Cloaked in the build definition, since this will cause the build to fail.
What we ended up doing was described in this answer: https://stackoverflow.com/a/3140349/1230302
So by adding the ExcludeFoldersFromDeployment statement to the .csproj file, the Content folder is excluded from the webroot.
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\</OutputPath>
<ExcludeFoldersFromDeployment>Content</ExcludeFoldersFromDeployment>
</PropertyGroup>
It is not an ideal solution, but at least this way nothing gets deployed if a developer forgets to set the build action to None.
The built in continuous delivery options are designed for convenience. Of you need something custom, like skipping deployment of files that have not changed, then you will need to write something yourself.
You can easily call PowerShell to complete any task from the build process.
If you'd like to customize your build as part of the VSO build system, you can just override your BuildTemplate.xaml file.
Visual Studio Build uses Windows Workflow (xaml) to make a workflow on what the build is supposed to do. You can edit this file and do any modifications to the directory structure before or after the build.
Here is an example.

What parameters does TeamCity pass to MSBuild under the covers?

I just downloaded TeamCity 7 today and decided to get it up and running for my Azure solution. I am not trying to do anything fancy (yet) and started with a very basic command line build:
msbuild /t:Publish /p:Configuration=Release;TargetProfile=Production;PublishDir=S:\HoursTracker\Deployments
This builds successfully and produces a package that looks like this*:
I then attempted to configure TeamCity in an identical fashion:
This builds successfully and produces a package that looks like this*:
What I don't understand is why there is such a huge discrepancy in the size of the MVC project. Publishing directly from Visual Studio produces the exact same result as my MSBuild command so I'm convinced that TeamCity is the odd man out. Since I assume TeamCity is not broken, can someone please educate me on how to properly configure it so that I get the expected output?
*I have renamed the package files with .zip so that the details were viewable for this post.
Ming's answer helped me solve the mystery. After inspecting the contents of the zip files, I discovered the difference was that my MSBuild package contained bin and obj folders and the TeamCity package did not.
After making this discovery, I realized that I could specify multiple targets to MSBuild and prepended "Clean" to my targets switch like so:
msbuild /t:Clean;Publish /p:Configuration=Release;TargetProfile=Production;PublishDir=S:\HoursTracker\Deployments
As expected, this removed those folders. So apparently, TeamCity specifies "Clean" implicitly for you. Mystery solved.
Windows Azure packages may be larger than we expect. You can rename the cssx file to zip and you will find out what’s inside the package. In addition to the web application’s usual files, there’re a bunch of Windows Azure files. For example, if you enable diagnostics, you will see a diagnostics folder, where you’ll find files used by Windows Azure diagnostics runtime.
Best Regards,
Ming Xu.
Why you specified x64 for msbuild runner? Try selecting tools version as well. You have not specified /p:Platform parameter. Does publish task involve rebuild?
TeamCity starts msbuild with number of /p: parameters taken from " properties and environment variables " section, plus some well-known parameters like configuration name or project name.

allowDefinition='MachineToApplication' msbuild error

We have a ASP.NET MVC with 4-5 different build configurations. Whenever we change the build configuration, we need to delete the obj folder for the web project, since we get the 'allowDefinition='MachineToApplication' error. A pain, but we managed by deleting the folder in pre/post build events.
Now I need to configure our CI to build deployment packages. This means that I cannot delete the obj folder. Every time I compile e.g. with the following msbuild parameters
/p:CreatePackageOnPublish=true /p:DeployOnBuild=true
I recieve the error:
web.config(123): error ASPCONFIG: It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS.
As far as I understand, the problem is that there's multiple .config files in the project - In our case, there's not. I could really use some help to find an explanation and find a permanent (no- hack) fix.
Edit:
This question is marked as a duplicate, but the corresponding answers and cause(s) in the 2 threads, are clearly different from each other. Not sure what is intended with this tag - I've read that particular post before posting this question, as it didn't answer my question. There's multiple causes for this error message. It is 'similar', but definitely not a duplicate!
There is a similar question here on SO with some good solutions for this issue.
The problem is that building a deployment package creates a copy of the web.config in a subfolder of /obj. That will normally be be cleared out if you do a rebuild or a clean. However, if you build a deployment package in one configuration (e.g. Debug) and then switch to another confguration (e.g. Release) the obj/Debug folder is not cleared out and the web.config file there causes problems.
The quick solution is to clean all configurations and then do a (re)build. Alternatively you could delete the /obj folder in your project.
To permanently resolve the issue you can either move the intermediate output (/obj) out of your project folder or modify the project to force a clean of all configurations on rebuild.
I too was deleting the obj folder until I had a conflict with a build script which required it. Catch-22, I used the accepted answer on the following SO link to move the location of the Obj folder to C:\Temp\BUILD. You have to do it per csproj file, but it is a great solution.
Here is the link: VisualStudio: How to save the obj folder somewhere else
Note that I am using a variable for the project name.
R:\Temp\Build\Debug\$(MSBuildProjectName)
I have the above line in both debug and release sections for all my projects, including class projects. My build path is a ram drive for speed. See this SO for more info: How to access macro variables within csproj file?
I just answered a similar question here. To recap, I ran into this problem in one of our MVC projects, and it was due to having the MvcBuildViews property in the project file set to true. Setting the property to false fixed the problem.
<MvcBuildViews>false</MvcBuildViews>
I also found this answer which outlines an alternative that does not require turning off view building.
I don't know that there is an "official" fix as it just seemed to start on multiple projects of mine for no reason that I can find in Visual Studio Premium 2012 (never happened in previous versions of VS).
As a work around to automate the deletion of the obj directory as others have said, similar to an answer by user Casual in this post VisualStudio: How to save the obj folder somewhere else, where unfortunately just moving the location of the obj folder didn't always seem to work.
Instead I added a few commands under Build Events in the Pre-build event command line:
rd "$(ProjectDir)obj" /S /Q
md "$(ProjectDir)obj"
md "$(ProjectDir)obj\Debug"
md "$(ProjectDir)obj\Release"
You can change/add/remove subfolders to match your custom build configurations using the line where buildConfigName matches the name of the build configuration you are using:
md "$(ProjectDir)obj\buildConfigName"
Hope this helps!
That error indicates that you are trying to something specific to an application at an IIS tree level that isn't defined as an application. For example if you try to do app-level functions in a web.config in a virtual directory, you will get that error. You need to find the path you are deploying to and make sure that it is defined in IIS as an application vs a folder or vdir.
Cleaning the solution (Right click Solution in VS, clean), worked for me.
I had the same error but with a deployed page.. Then realized my webserver's clock was set back to 2010 for some reason. set it to the correct date fix my problem
Clean your project
Remove the /obj folder (probably using publish and deploy? - there is a bug in it)
Althoug the problem is explained and solved in one way in the accepted answer, I wanted to show a solution which can be better for other cases. This solution has been included in some version of VS, but I can only say that I had the problem in VS 2013 Update 5. (See the "Beware" below, it could be fixed in this version, but not working only in my particular case).
I borrowed the soltuion from Error: allowDefinition='MachineToApplication' beyond application level on Visual Studio Connect.
The solution consist in including these lines to the web application project (.csproj file) which handle the deletion of the offedning intermediate files (which wans't a solution for the accepted answer, as he needed those intermediate files):
<!--Deal with http://connect.microsoft.com/VisualStudio/feedback/details/779737/error-allowdefinition-machinetoapplication-beyond-application-level,
we will need to clean up our temp folder before MVC project starts the pre-compile-->
<PropertyGroup>
<_EnableCleanOnBuildForMvcViews Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='' ">true</_EnableCleanOnBuildForMvcViews>
</PropertyGroup>
<Target Name="CleanupForBuildMvcViews" Condition=" '$(_EnableCleanOnBuildForMvcViews)'=='true' and '$(MVCBuildViews)'=='true' " BeforeTargets="MvcBuildViews">
<ItemGroup>
<_PublishTempFolderNamesToCleanup Include="Database;TransformWebConfig;CSAutoParameterize;InsertAdditionalCS;ProfileTransformWebConfig;Package;AspnetCompileMerge" />
</ItemGroup>
<!--Force msbuild to expand all the wildcard characters so to get real file paths-->
<CreateItem Include="#(_PublishTempFolderNamesToCleanup->'$(BaseIntermediateOutputPath)**\%(identity)\**\*')">
<Output TaskParameter="Include" ItemName="_EvaluatedPublishTempFolderNamesToCleanup" />
</CreateItem>
<Delete Files="#(_EvaluatedPublishTempFolderNamesToCleanup)" />
</Target>
Beware: for some reason, probably because I included it myself in the project, my build target for building the views was named "BuildViews", instead of "MvcBuildViews", so I had to modify the BeforeTargets attribute accordingly.
This is not necessarily the exact same issue, and to be honest, probably down to pure lack of knowledge on my part, however I had this same error when:
I set up a standard asp.net new project actually just used for HTML5 stuff so nothing other than the usual project structure
I then (not thinking perhaps!) added a new WCF REST project (which actually was just another base asp.net project using very good examples from http://www.codeproject.com/Articles/128478/Consuming-WCF-REST-Services-Using-jQuery-AJAX-Call?fid=1597004&df=90&mpp=25&noise=3&prof=False&sort=Position&view=Quick&fr=26#xx0xx and http://geekswithblogs.net/michelotti/archive/2010/08/21/restful-wcf-services-with-no-svc-file-and-no-config.aspx
The problem was I added the WCF REST project (#2) as a SUB-DIRECTORY of the main project (#1) and then tried to build! even if I cleaned the project of course.. I also made both projects use IISexpress because I thought there was an issue using the same port or something.
Of course the build process saw the web.config from #1 and then a sub-dir with another web.config #2..
I realise this probably should be a very basic understood gotcha and it has caught me out a while ago, however sometimes it's the simplest of mistakes that are a real pain!
Might help others... who perhaps haven't had their morning coffee..
tip 1: clean & then rebuild.
tip 2: just close VS and open again.
tip 3: the downloaded project may be inside another sub folder... open the folder which has you .net files.
c:/demo1/demo/ (all files)
You should have to open demo from vs... not demo1.
I have a somewhat a similar problem, i had the main config as Copy Always so it copied the config to the bin directory. When i republished the main project, i got the MachineToApplication error. So my solution was to just change the config to Do Not Copy and remove the extra configuration in the bin folder.

MSBuild target _CopyWebApplication does not copy all necessary files to the bin folder

Elsewhere on the Web, you can find recommendations on using something like this to simulate the Publish feature in the VS 2005-2008 IDE from a command-line (I hope I did not goof up the syntax!):
msbuild /t:ResolveReferences;_CopyWebApplication /p:BuildingProject=true;OutDir=C:\inetpub\wwwroot\ blah.csproj
Now, it looks like the .dll's copy fine. However, there are certain configuration files and template files that are copied to the bin folder which are needed for the app to work. For example, an NHibernate configuration file shows up in blah.csproj as:
<None Include="blah.cfg.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
While using Publish from within the IDE copies this file as it should, the aforementioned _CopyWebApplication target does not. I need this file to be copied in the build script. Is this desired behavior for _CopyWebApplication? Any recommendations on how to fix this?
EDIT 4/21/2010:
Let me clarify that we are limited (for now) to VS 2005 and VS 2008 projects, and that our build scripts are written for MSBuild 3.x. We are not yet ready to move to VS 2010.
Let me also specify that we are looking for a solution available from within a command line so that we can automate a Publish-like command along with custom build options, and possibly automate deployments down the road.
This is just a workaround.
In the build script for publishing Web sites, after running MSBuild on the Web project itself to publish it (Targets="ResolveReferences;_CopyWebApplication"), I added a copy operation:
<Copy SourceFiles="#(ProjectBinFiles)" DestinationFolder="$(StageBin)\%(ProjectBinFiles.RecursiveDir)" />
where ProjectBinFiles is an Item representing the files in the bin directory in the source directory, and StageBin is a Property representing the bin folder in the published site's directory. So far, it seems to work.
I was having a similar issue as well. I think the answer is using MSDeploy. Investigating it now, but may provide functionality required...
I had this same issue in VS 2012 and eventually fixed it by doing the following to any files which needed to be copied:
Set the Copy to Output file property to Copy if newer
Set the Build Action file property to Content (or Compile if the file needs to be compiled)