This is a smaller question related to my overall problem. This is what I am trying to accomplish.
Ive created a task that modifies my source files. Whenever I compile and build, I want to compile with the modified cs files. Ive attempted to make a console application that I call from the prebuild event but I found that only some of the modified files were compiled. Even when I did not have them opened in the editor. Then I attempted to use a custom task which works with the following xml in my csproj file:
<Target Name="BeforeCompile">
<MyCustomTask />
</Target>
And I also used this to get the same result:
<PropertyGroup>
<CompileDependsOn>
$(CompileDependsOn);
MyCustomTarget;
</CompileDependsOn>
</PropertyGroup>
<Target Name="MyCustomTarget">
<MyCustomTask />
</Target>
So this does what I want to do, but I found that whenever I load the project file, it triggers my target. I would assume that this would only run when my code is being compiled. So apparently, it is compiling or compile related targets are being triggered when the project file loads.
Ideally, I want this target to trigger only when I explicitly build my project (i.e. manually building or when I start debugging). What can I do differently to achieve this?
From the documentation, these targets are always executed as part of the loading of Visual Studio. That will also include any dependencies these targets have.
When comparing which targets are executed when running
msbuild /v:diag /t:compile
vsmsbuild /v:diag /t:build
you'll see thatResGen
and a few other targets are skipped. Trying to piggyback on one of these may do the trick for you.Also keep in mind these things about the Visual Studio Hosting process and the effect it has on dynamically changed files:
The Visual Studio compiler may be using it's cached version of the files. Which will cause issues, either explicitly create the files under the
obj
folder and include them in MsBuild dynamically, that way Visual Studio will not use it's in-memory instance of the file. Do this by removing the source file from the ItemGroup and adding your own generated copy instead, you'll need to do this from your custom target:Instead of hard coding it, you could also use a transformation expression:
Alternatives
Disable the host compiler
Or disable the HostCompiler by adding
to the first propertygroup (that should not have a condition on it) to make Visual Studio always use the disk version (will slow down Visual Studio builds slightly).
Make your task Visual Studio aware
Or make your build task aware of the
IVsMSBuildTaskFileManager
and tell it when you update the files. You will need to register your build task in the registry of Visual Studio to flag it as "safe to load".