It so happens quite often that I start by building some solution on the command line using msbuild, run it for awhile, but then discover that I need to change and debug it. So, I open it in Visual Studio and end up building it inside the Visual Studio.
What happens is that VS rebuilts quite a few parts of the solution, even when I change nothing!
Digging into it reveals the following:
Building inside Visual Studio generates empty cs files and injects them into the Compile
item group. Naturally, they are newer than the already built binaries and so devenv.exe rebuilds an awful lot of projects. Thanks to TemporaryGeneratedFile_[guid] in /obj/debug breaking build
This is a real bummer. I disabled this behavior by renaming the Microsoft.WorkflowBuildExtensions.targets
file - I do not do workflow.
I suppose I could hack into CoreCompileDependsOn
and somehow neutralize the GenerateCompiledExpressionsTempFile
target from Microsoft.WorkflowBuildExtensions.targets, but this has to be done in 190 projects! This is a serious change.
devenv.exe seems to care about some files always being copied to the output directory, even if msbuild does not think it is a problem.
Indeed, here is a line from the devenv.exe build log:
Project 'HRCore.Tests' is not up to date. Project item 'C:\abc\UI\HRCore.Tests\HRImport\Import_missing_state_county.xml' has 'Copy to Output Directory' attribute set to 'Copy always'.
So what? msbuild does not care about it, but devenv does. This files is not a dependency of the HRCore.Tests
and msbuild got it right.
In the meantime I changed it from Always
to PreserveNewest
.
Anyway, I am interested to know how can I eliminate these differences.
For example, is it a good idea to set BuildingInsideVisualStudio
to true
even when building with msbuild?
Any ideas?
P.S.
We build both .NET and Silverlight. Console applications, dlls and web applications.
That
.targets
file indeed causes different behavior between Visual Studio and command line MsBuild due to the explicit check for$(BuildingInsideVisualStudio)
:That explicit check makes the temp file generation only occur in Visual Studio in my configuration. These files are made so that you can step into them and debug them when running inside Visual Studio.
The behavior can be turned off by overriding
<GenerateCompiledExpressionsTempFilePathForEditing />
to empty in your project file of clearing it's value explicitly on the commandline.This is the condition that guards this behavior:
Looking at the MsBuild path, you should be able to turn off the generation of compiled expressions completely by passing
/p:DisableWorkflowCompiledExpression=true
on the commandline on.You can also override
CoreCompileDependsOn
and remove theGenerateCompiledExpressionsTempFile;
item from it.It's really a pitty when there is "special behavior" when buildign inside the editor. In the end, I'd always err towards making Visual Studio behave as MsBuild and not the other way around. Many other targets will assume special services or the availability of the Host Compiler when
BuildingInsideVisualStudio
is true, it seems a very bad idea to make MsBuild think it's inside Visual Studio while it actually isn't.Another useful solution on this page suggested suggested several alternatives, of which clearly the best is to remove the
GenerateCompiledExpressionsTempFile
target fromCoreCompileDependsOn
property. Unfortunately, that property is, well..., an MSBuild property, as opposed to an MSBuild item, so removing a specific part of it isn't totally straightforward.[note 1.]This is perhaps why @jessehouwing went on to suggest other ways of preventing the Microsoft.WorkflowBuildExtensions target from running--and therefore adding those three annoying
.cs
files to every compile, namely, by tweaking some of the ambient MSBuild values the target examines when deciding what to do.So now to my small contribution... Why manipulate the factors the unwanted target considers, trying to trick it not to run, when you can simply blank-out the whole Target itself?
Just add the following line to the bottom of your
.csproj
project file:Notes:
1. Removing a delimited item from a property is certainly possible in MSBuild, using inline
$([System.String]::Replace(...))
, for example.