I have a file structure like the following:
- binaries
- binary1.dll
- dev
- <developer-name>
- a.csproj
-trunk
- a.csproj
Developers who need to work on a.csproj will create a branch in dev and they will work from there. Our projects need to have a reference to binary1.dll in the binaries directory.
If the reference is a relative path (the Visual Studio default) then the path will not work both for the project in trunk and the project in the developer's branch.
To work around this problem I thought of creating an environment variable and using that in the project file instead:
<Reference Include="binary1">
<HintPath>$(MY_ENV_VAR)\binary1.dll</HintPath>
</Reference>
This works perfectly, but I wanted to help developers add references more easily, so I wrote a program that will convert relative paths that point to binary1.dll (for example, from the dev branch a.csproj it would change the path ../../binaries/binary1.dll to $(MY_ENV_VAR)\binary1.dll) but I have not figured out how to get that to work.
If I use a pre-build event, the project is already loaded into memory and the event return an error because it cannot write the project file.
Then I realized that I could override MSBuild targets, and attempted with the targets: BeforeCompiler, AfterCompiler, BeforeBuild, AfterBuild and in all of them the project is already locked.
Then I ran into this answer and I modified my code to call the executable in the GenerateApplicationManifest target, but that one doesn't seem to call the executable at all.
Some other ideas that I have been playing with are creating a new project that does the updating of the second project and have a link between them, but that would duplicate the number of projects.
I could also just change the depth of trunk, but that only hides the problem and doesn't really solve it. When developers create a branch inside their dev branch to work on different features or bugs then I have the same problem all over again.
There might also be another feature which fixes this in a more elegant way, but I haven't been able to find anything.
So my question: How do I get MS Build or pre-build events to modify a CS project?
I found a way to do this. The issue was that the Visual Studio process itself was locking the project, but Visual Studio could overwrite the file. I ended up modifying a.csproj to include:
<Target Name="BeforeBuild">
<Exec Command="UpdateReferences.exe" /> <!-- This creates the $(ProjectPath).new file -->
<Move SourceFiles="$(ProjectPath).new" DestinationFiles="$(ProjectPath)" />
</Target>
Related
Following my previous question, I want to change TargetFrameworks for each developer on their machine only. However, I cannot find anyway to modify it without pushing something into our Git source control. Assuming we have a dev who works on Android and one who works on iOS, how should we do that?
Currently I can use Environment Variable but changes are not applied until VS is restarted and cleaning the project always results in some strange error until the 2nd restart.
<TargetFrameworks></TargetFrameworks>
<TargetFrameworks Condition="$(MAUI_BUILD.Contains('win'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<TargetFrameworks Condition="$(MAUI_BUILD.Contains('and'))">$(TargetFrameworks);net7.0-android</TargetFrameworks>
<TargetFrameworks Condition="$(MAUI_BUILD.Contains('ios'))">$(TargetFrameworks);net7.0-ios</TargetFrameworks>
<TargetFrameworks Condition="$(MAUI_BUILD.Contains('mac'))">$(TargetFrameworks);net7.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$(MAUI_BUILD.Length)==0">$(TargetFrameworks);net7.0-windows10.0.19041.0;net7.0-android;net7.0-ios;net7.0-maccatalyst</TargetFrameworks>
Is there a better way to accomplish this? If possible, I'd like to have it to be project-specific. For example we may have a TargetConfig.txt file in our project folder for example and we add that file into our .gitignore. Or something like project.Development.csproj like web.config transformation would be great too.
Note that the solution need to work on VS for Mac as well though I think there's no difference between MSBuild on Windows and Mac.
UPDATE: somehow my environment variable workaround doesn't even work on MacOS.
Add .user to your .gitignore. Add a file with the name of your project and the .user extension as a peer of the project file.
e.g.
project1\
project1.csproj
project1.csproj.user
Place the per-user customizations in the .user file.
See Customize your build.
We have a C# solution with multiple projects. We are managing version control for the solution using Github desktop, i.e., outside Visual Studio. After pushing new code to GitHub on a new machine with a fresh install of Visual Studio 2019 community edition, when I add a new file to the API project in the solution, I find that the file gets added to the .csproj file as follows, and the IDE never includes the file in the build, debugging, code completion etc.
<ItemGroup>
<Compile Remove="Controllers\TestController.cs" />
</ItemGroup>
I also see a + sign next to the TestController file in Solution Explorer. Hovering over the + sign brings up the message "pending add."
Why is this happening? And is it safe to just remove this itemgroup block in the .csproj file? Is there a way to prevent this behavior for new files added to the project?
Details
Context:
C# solution with 5 projects - (1) WebAPI, (2) Identity, (3) DataAccess, (4) Services, (5) Shared libraries. Editing using Visual Studio 2019 Community Edition.
Full timeline:
Solution pulled from GitHub.com using GitHub desktop
Files added to DataAccess and Services project using Visual Studio. Everything was fine
New branch created in GitHub desktop. New files added to the branch using GitHub desktop and pushed to GitHub.com using GitHub desktop
Code merged with parent branch by project administrator
Local solution synced to remote repository using GitHub desktop
--- alert: problem seen now ---
New file (TestController) added to the API project using Visual Studio. This file does not become part of the build. IDE does not highlight ApiControllers, ControllerBase etc, does not indicate errors for mis-spelt services, pressing F11 on ApiControllers gives error message "cannot navigate to the symbol under the caret."
Google search suggests checking on .csproj file. Here I find that the new file is within the 'compile remove' block.
Is it safe to edit .csproj file in Visual Studio 2019?
If you know what you're doing and you do it correctly, sure. Otherwise, not so much.
Why is this happening? And is it safe to just remove this itemgroup block in the .csproj file? Is there a way to prevent this behavior for new files added to the project?
It's happening because a file showed up in the project subdirectory that Visual Studio doesn't have as part of that project. So it adds the <Compile Remove... /> element to exclude it from being compiled as part of the project. It is safe to remove the element, but in my experience it just shows up again.
As a general rule, you should not be adding files to project directories managed by Visual Studio, except by using the Visual Studio UI itself. It's not clear from your post why you are doing this. The directory you apparently are adding files to is your project directory. It should only have files that do in fact belong to the project.
The best fix is to not try to add files to a project directory when they shouldn't be part of that project.
You may have an XY Problem. If you can post a new question in which you explain the scenario in which you've added the files that don't belong, and ask for guidance to accomplish whatever broader goal it is you have, but without running afoul of Visual Studio's rules, you may get a better answer than "don't do that".
I think I have identified the problem. I believe what happened is that once the local branch was pushed to remote, further changes to the project made using Visual Studio were not being integrated into the project, even though I was not formally tracking the project in Visual Studio.
git status showed that I was still on my initial local branch. I did the following to sync with the remote parent branch and then start a new local branch:
git stash
git checkout <parent_branch>
git pull
git checkout -b <new_branch>
This switched me to a new branch, and now I am able to edit the file as usual.
I have a sln with > 50 projects, and recently, when I moved to VS2013, every time I press F5 for a build, it will rebuild all the projects, even though I have just performed a build. The diagnostics show, that each project is marked as not up to date with the following error:
Project <PROJECT NAME> is not up to date. Missing input file 'c:\users\USER\appdata\local\temp\2\.netframework,version=v4.0,profile=client.assemblyattributes.cs
I have read these threads:
In Visual Studio 2010 why is the .NETFramework,Version=v4.0.AssemblyAttributes.cpp file created, and can I disable this?
https://social.msdn.microsoft.com/Forums/vstudio/en-US/15d65667-ac47-4234-9285-32a2cb397e32/migration-from-vs2008-to-vs2010-and-netframeworkversionv40assemblyattributescpp?forum=vcgeneral
but the suggestion there is to add the following line to the proj file:
<Target Name="GenerateTargetFrameworkMonikerAttribute" />
I did and it did not work. Suppressing the warning as MS suggestion will also not work as the project will remain "not up to date".
I am using VS2013, C# and VB projects. With the very same project and VS2012, such error is not raised and the projects are up to date.
Any suggestions?
UPDATE
Perhaps it is worth mentioning that I do have a few build definitions in the solution, where all of the projects are building for AnyCPU except one: http://screencast.com/t/fuw9k4IubN
I had the same problem and solved it by upgrading the ToolsVersion attribute in *.csproj files:
ToolsVersion="4.0" replaced with ToolsVersion="16.0"
(I’m using Visual Studio 2019, which is v16.x internally).
<Target Name="GenerateTargetFrameworkMonikerAttribute" />
Well, not a good idea, that accomplishes the exact opposite of the problem you are trying to solve. It forces MSBuild to create the AssemblyAttributes.cs file, inevitably your project needs to be rebuilt since the file is new. The Q+A you found addresses a completely different issue, these were C++ programmers that were trying to come to grips with a new linker warning in VS2010. They hate warnings that appear from nowhere from files that are not part of their project. Well, don't we all. The marked answer on that SO question is quite evil btw, that other guy posted a much better answer :)
Missing input file 'c:\users\USER\appdata\local\temp\2\.netframework...
There's a signal in this message, note the presence of the \2 subdirectory in that path name. That is a Big Red Flag, it is not normal. This auto-generated .cs file normally lives inside the TEMP directory, not a subdirectory of that folder. Surely this has something to do with your real problem.
MSBuild doesn't do anything special and simply uses System.IO.Path.GetTempPath() to generate the folder name. That method isn't special either, it simply delegates the job to the GetTempPath() winapi function. The diagnostic therefore is that on this build machine, that OS function sometimes generates an odd-ball path, picking a subdirectory of the TEMP folder. And that it doesn't always generate the same one, thus causing your projects to getting rebuilt.
There is at least one good theory for this behavior, mentioned by commenter #Darran Rowe to this blog post:
No, this is Terminal Services at work. When you log in over remote desktop, Windows will set the temp directory for the logon session to %LOCALAPPDATA%\Temp\<session id>
Rings a bell?
Try deleting the hidden .vs directry which is in the same folder than the solution file.
This worked for me
Close visual studio and Deleted the .sou files from the projects
I was getting the same error and I solved it by removing the project from my solution and re-adding it. It is a pain because then you have to add the inter project references back in.
I've got a Visual Studio 2013 package written in C# where I need to make some changes in the items and their attributes in a C++ project file while Visual Studio 2013 is running and has the project loaded. Actually, it could also be OK to save the project file at the point when the whole solution is being saved.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="Test">
<MyItemToChange Include = "TestItem">
<MyMetadata1ToChange>Value1</MyMetadata1ToChange>
<MyMetadata2ToChange>Value2</MyMetadata2ToChange>
</MyItemToChange>
</ItemGroup>
<!-- The rest of the file -->
</Project>
In previous Visual Studio versions I used the Microsoft.Build.Evaluation.Project class to change the items and the metadata of the project. When you have the reference to the project, you can either accessed the XML structure of the project directly through Project.Xml property or get a hold on different Microsoft.Build.Evaluation.ProjectItem and use the interfaces found there.
However, since Microsoft has changed the structure of Visual Studio in their 2013 release, though the Microsoft.Build.Evaluation.Project is not deprecated, you can't access the C++ projects any more through Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.LoadedProjects as the collection is empty. However it still works if you want to access C# projects. (As a matter of fact, browsing deep into the objects while debugging you can find that they still use the same Microsoft.Build.Evaluation namespace for inner representation.)
Since I can't access the Microsoft.Build.Evaluation.Project any more, I need an alternative to
access the project otherwise than using the
Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.LoadedProjects
write project items and metadata while Visual Studio 2013 is running.
Unless I've missed something, the following are not good for my purposes:
Microsoft.VisualStudio.Shell.Interop.IVsBuildPropertyStorage.SetItemAttribute sets only attributes to items that are displayed in the Solution Explorer. "MyItemToChange" is not displayed in the Solution Explorer
Opening the file and manually editing and saving it. Unless you know how to suppress Visual Studio's warning about a changed project and how to auto reload it, it is not a way to go.
Note: You can close the solution, open the project file manually, edit then save it and reopen the solution. It would work fine, the data is there, unless the files are under source control. Now it opens up a whole lot of new issues (why EnvDTE.DTE.SourceControl.CheckOutItem() doesn't work, etc.) So I still think I would be better off if Visual Studio would handle writing data to the project file.
Reflection. Yes, as I mentioned before, I could dig into internal classes to get a hold on the "original" Microsoft.Build.Evaluation.Project, and Microsoft.Build.Evaluation.ProjectItem, but first of all, it is quite unsafe for future uses and as far as I remember, you cannot be sure that if you modify these now internal classes, the project will know that it is dirty and has to be saved.
I'm glad to have any suggestions as I'm really running out of options.
Thanks.
Well, I have worked out a workaround, not a real solution for the problem.
What I do right now is the following:
Ask the user whether they're OK with closing the whole solution and saving everything. If not, I cancel the whole procedure: EnvDTE.DTE.ItemOperations.PromptToSave
Try to ask Visual Studio 2013 to check out the project file for me in source control using EnvDTE.DTE.SourceControl.CheckOutItem() method. If it throws an exception (NotImplementedException), I use a bodge to check out the project file. That is, I write a custom property into the project file using Microsoft.VisualStudio.Shell.Interop.IVsBuildPropertyStorage.SetProperty() method.
Close the whole solution. EnvDTE.DTE.Solution.Close()
Open the project file using the System.Xml.XmlDocument class. Edit. Save. Oh, and remove my silly property written in the 2. point (the one used to force Visual Studio 2013 to check out the file in source control.)
Reopen the solution. EnvDTE.DTE.Solution.Open() At this point the user might be asked again to confirm some source control options.
Why is it just a workaround not a proper solution?
It's ugly. :)
Methods are abused for things they are not meant to be used (writing a random property into a project just to force source control checkout)
It wouldn't work if closing the solution / project is not an option. E.g.: if you need to save something during build or while they are editing the solution / project / source files; or if you have to do it often not just once during the lifetime of a project.
I'm still looking for the proper solution for the problem. But until someone could tell me how it is done, I have to live with this current implementation.
I have a c# .Net 4.0 project created with VS2010 and now being accessed with VS2012.
I'm trying to publish only the needed files from this website to a destination location (C:\builds\MyProject[Files])
My file structure:
./ProjectRoot/MyProject.csproj
./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml
I'm running the following via MSBuild:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml
Here's the xml in FileSystemDebug.pubxml
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<ExcludeApp_Data>False</ExcludeApp_Data>
<publishUrl>C:\builds\MyProject\</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
</PropertyGroup>
</Project>
The resulting behavior is:
a zip file is created here:./ProjectRoot/obj/Debug/Package/MyProject.zip
Nothing is deployed to <publishUrl>C:\builds\MyProject\</publishUrl> WTF
the zip file that is created is a pigs breakfast and full of files that aren't needed for the application.
When I run this publish profile through visual studio a folder is created at *C:\builds\MyProject* and contains the exact artifacts that I want.
How do I get this simple result from msbuild?
FYI: I had the same issue with Visual Studio 2015. After many of hours trying, I can now do msbuild myproject.csproj /p:DeployOnBuild=true /p:PublishProfile=myprofile.
I had to edit my .csproj file to get it working. It contained a line like this:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets"
Condition="false" />
I changed this line as follows:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0\WebApplications\Microsoft.WebApplication.targets" />
(I changed 10.0 to 14.0, not sure whether this was necessary. But I definitely had to remove the condition part.)
Found the answer here:
http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
Visual Studio 2010 has great new Web Application Project publishing
features that allow you to easy publish your web app project with a
click of a button. Behind the scenes the Web.config transformation and
package building is done by a massive MSBuild script that’s imported
into your project file (found at: C:\Program Files
(x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets).
Unfortunately, the script is hugely complicated, messy and
undocumented (other then some oft-badly spelled and mostly useless
comments in the file). A big flowchart of that file and some
documentation about how to hook into it would be nice, but seems to be
sadly lacking (or at least I can’t find it).
Unfortunately, this means performing publishing via the command line
is much more opaque than it needs to be. I was surprised by the lack
of documentation in this area, because these days many shops use a
continuous integration server and some even do automated deployment
(which the VS2010 publishing features could help a lot with), so I
would have thought that enabling this (easily!) would be have been a
fairly main requirement for the feature.
Anyway, after digging through the Microsoft.Web.Publishing.targets
file for hours and banging my head against the trial and error wall,
I’ve managed to figure out how Visual Studio seems to perform its
magic one click “Publish to File System” and “Build Deployment
Package” features. I’ll be getting into a bit of MSBuild scripting, so
if you’re not familiar with MSBuild I suggest you check out this crash
course MSDN page.
Publish to File System
The VS2010 Publish To File System Dialog Publish to File System took
me a while to nut out because I expected some sensible use of MSBuild
to be occurring. Instead, VS2010 does something quite weird: it calls
on MSBuild to perform a sort of half-deploy that prepares the web
app’s files in your project’s obj folder, then it seems to do a manual
copy of those files (ie. outside of MSBuild) into your target publish
folder. This is really whack behaviour because MSBuild is designed to
copy files around (and other build-related things), so it’d make sense
if the whole process was just one MSBuild target that VS2010 called
on, not a target then a manual copy.
This means that doing this via MSBuild on the command-line isn’t as
simple as invoking your project file with a particular target and
setting some properties. You’ll need to do what VS2010 ought to have
done: create a target yourself that performs the half-deploy then
copies the results to the target folder. To edit your project file,
right click on the project in VS2010 and click Unload Project, then
right click again and click Edit. Scroll down until you find the
Import element that imports the web application targets
(Microsoft.WebApplication.targets; this file itself imports the
Microsoft.Web.Publishing.targets file mentioned earlier). Underneath
this line we’ll add our new target, called PublishToFileSystem:
<Target Name="PublishToFileSystem"
DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
<Error Condition="'$(PublishDestination)'==''"
Text="The PublishDestination property must be set to the intended publishing destination." />
<MakeDir Condition="!Exists($(PublishDestination))"
Directories="$(PublishDestination)" />
<ItemGroup>
<PublishFiles Include="$(_PackageTempDir)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(PublishFiles)"
DestinationFiles="#(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')"
SkipUnchangedFiles="True" />
</Target>
This target depends on the
PipelinePreDeployCopyAllFilesToOneFolder target, which is what VS2010
calls before it does its manual copy. Some digging around in
Microsoft.Web.Publishing.targets shows that calling this target causes
the project files to be placed into the directory specified by the
property _PackageTempDir.
The first task we call in our target is the Error task, upon which
we’ve placed a condition that ensures that the task only happens if
the PublishDestination property hasn’t been set. This will catch you
and error out the build in case you’ve forgotten to specify the
PublishDestination property. We then call the MakeDir task to create
that PublishDestination directory if it doesn’t already exist.
We then define an Item called PublishFiles that represents all the
files found under the _PackageTempDir folder. The Copy task is then
called which copies all those files to the Publish Destination folder.
The DestinationFiles attribute on the Copy element is a bit complex;
it performs a transform of the items and converts their paths to new
paths rooted at the PublishDestination folder (check out Well-Known
Item Metadata to see what those %()s mean).
To call this target from the command-line we can now simply perform
this command (obviously changing the project file name and properties
to suit you):
msbuild Website.csproj "/p:Platform=AnyCPU;Configuration=Release;PublishDestination=F:\Temp\Publish" /t:PublishToFileSystem
Still had trouble after trying all of the answers above (I use Visual Studio 2013). Nothing was copied to the publish folder.
The catch was that if I run MSBuild with an individual project instead of a solution, I have to put an additional parameter that specifies Visual Studio version:
/p:VisualStudioVersion=12.0
12.0 is for VS2013, replace with the version you use. Once I added this parameter, it just worked.
The complete command line looks like this:
MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0
I've found it here:
http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/command-line-deployment
They state:
If you specify an individual project instead of a solution, you have to add a parameter that specifies the Visual Studio version.
It looks to me like your publish profile is not being used, and doing some default packaging. The Microsoft Web Publish targets do all what you are doing above, it selects the correct targets based on the config.
I got mine to work no problem from TeamCity MSBuild step, but I did specify an explicit path to the profile, you just have to call it by name with no .pubxml (e.g. FileSystemDebug). It will be found so long as in the standard folder, which yours is.
Example:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=FileSystemDebug
Note this was done using the Visual Studio 2012 versions of the Microsoft Web Publish targets, normally located at "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web". Check out the deploy folder for the specific deployment types targets that are used
Actually I merged all your answers to my own solution how to solve the above problem:
I create the pubxml file according my needs
Then I copy all the parameters from pubxml file to my own list of parameters "/p:foo=bar" for msbuild.exe
I throw away the pubxml file
The result is like that:
msbuild /t:restore /t:build /p:WebPublishMethod=FileSystem /p:publishUrl=C:\builds\MyProject\ /p:DeleteExistingFiles=True /p:LastUsedPlatform="Any CPU" /p:Configuration=Release
FYI: Same problem with running on a build server (Jenkins with msbuild 15 installed, driven from VS 2017 on a .NET Core 2.1 web project).
In my case it was the use of the "publish" target with msbuild that ignored the profile.
So my msbuild command started with:
msbuild /t:restore;build;publish
This correctly triggerred the publish process, but no combination or variation of "/p:PublishProfile=FolderProfile" ever worked to select the profile I wanted to use ("FolderProfile").
When I stopped using the publish target:
msbuild /t:restore;build /p:DeployOnBuild=true /p:PublishProfile=FolderProfile
I (foolishly) thought that it would make no difference, but as soon as I used the DeployOnBuild switch it correctly picked up the profile.
First check the Visual studio version of the developer PC which can publish the solution(project).
as shown is for VS 2013
/p:VisualStudioVersion=12.0
add the above command line to specify what kind of a visual studio version should build the project. As previous answers, this might happen when we are trying to publish only one project, not the whole solution.
So the complete code would be something like this
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" "C:\Program Files (x86)\Jenkins\workspace\Jenkinssecondsample\MVCSampleJenkins\MVCSampleJenkins.csproj" /T:Build;Package /p:Configuration=DEBUG /p:OutputPath="obj\DEBUG" /p:DeployIisAppPath="Default Web Site/jenkinsdemoapp" /p:VisualStudioVersion=12.0
Run from the project folder
msbuild /p:DeployOnBuild=true /p:PublishProfile="release-file.pubxml" /p:AspnetMergePath="C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" /p:Configuration=Release
This takes care of web.config Transform and AspnetMergePath