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.
Design-Time Target Execution
Visual Studio attempts to execute targets with certain names when it loads a project. These targets include Compile, ResolveAssemblyReferences, ResolveCOMReferences, GetFrameworkPaths, and CopyRunEnvironmentFiles. Visual Studio runs these targets so that the compiler can be initialized to provide IntelliSense, the debugger can be initialized, and references displayed in Solution Explorer can be resolved. If these targets are not present, the project will load and build correctly but the design-time experience in Visual Studio will not be fully functional.
Source
When comparing which targets are executed when running msbuild /v:diag /t:compile
vs msbuild /v:diag /t:build
you'll see that ResGen
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:
<ItemGroup>
<Compile Remove="ThefileYourWantGone.cs" />
<Compile Include="$(BaseIntermediateOutputPath)\ThefileYourWantGone.g.cs/>
</ItemGroup>
Instead of hard coding it, you could also use a transformation expression:
<ItemGroup>
<Compile Include="ThefileYourWantGone.cs">
<IsRegenerated>true</IsRegenerated>
</Compile>
</ItemGroup>
<ItemGroup>
<RegeneratedCompile
Include="@(Compile)"
Condition="'%(Compile.IsRegenerated)' == 'true'"
/>
</ItemGroup>
<YourCustomtaskThatOutputs Inputs="@(RegeneratedCompile)" Outputs="@(RegeneratedCompile-> '$(BaseIntermediateOutputPath)\%(relativedir)%(filename).g.%(extension)')" />
<ItemGroup>
<Compile Remove="@(RegeneratedCompile)" />
<Compile Include="@(RegeneratedCompile-> '$(BaseIntermediateOutputPath)\%(relativedir)%(filename).g.%(extension)')" />
</ItemGroup>
Alternatives
Disable the host compiler
Or disable the HostCompiler by adding
<UseHostCompilerIfAvailable>FALSE</UseHostCompilerIfAvailable>
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".