这是一个与我的整体问题相关的小问题。这就是我想要实现的目标。
我创建了一个修改源文件的任务。每当我编译和构建时,我想用修改过的cs文件进行编译。我试图制作一个我从prebuild事件调用的控制台应用程序,但我发现只编译了一些修改过的文件。即使我没有在编辑器中打开它们。然后我尝试使用自定义任务,该任务在我的csproj文件中使用以下xml:
<Target Name="BeforeCompile">
<MyCustomTask />
</Target>
我也用它来得到相同的结果:
<PropertyGroup>
<CompileDependsOn>
$(CompileDependsOn);
MyCustomTarget;
</CompileDependsOn>
</PropertyGroup>
<Target Name="MyCustomTarget">
<MyCustomTask />
</Target>
所以这就是我想要做的,但我发现无论何时加载项目文件,它都会触发我的目标。我认为这只会在我的代码编译时运行。显然,在项目文件加载时,它正在编译或编译相关目标。
理想情况下,我希望只有在我明确构建项目时(即手动构建或开始调试时)才会触发此目标。为实现这一目标,我能做些什么?
答案 0 :(得分:4)
从文档中,这些目标始终作为加载Visual Studio的一部分执行。这也包括这些目标所依赖的任何依赖。
设计时目标执行
Visual Studio在加载项目时尝试执行具有特定名称的目标。这些目标包括编译, ResolveAssemblyReferences , ResolveCOMReferences , GetFrameworkPaths 和 CopyRunEnvironmentFiles 。 Visual Studio运行这些目标,以便可以初始化编译器以提供IntelliSense,可以初始化调试器,并且可以解析在解决方案资源管理器中显示的引用。如果这些目标不存在,项目将正确加载和构建,但Visual Studio中的设计时体验将无法完全发挥作用。
<子> Source 子>
在比较运行msbuild /v:diag /t:compile
vs msbuild /v:diag /t:build
时执行的目标时,您会看到ResGen
和其他一些目标被跳过。试图捎带其中一个可能会为你做到这一点。
Visual Studio编译器可能正在使用它的缓存版本的文件。这将导致问题,要么在obj
文件夹下显式创建文件并将它们动态地包含在MsBuild中,这样Visual Studio就不会使用它的文件内存实例。通过从ItemGroup中删除源文件并添加您自己生成的副本来执行此操作,您需要从自定义目标执行此操作:
<ItemGroup>
<Compile Remove="ThefileYourWantGone.cs" />
<Compile Include="$(BaseIntermediateOutputPath)\ThefileYourWantGone.g.cs/>
</ItemGroup>
您可以使用转换表达式,而不是对其进行硬编码:
<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>
禁用主机编译器
<UseHostCompilerIfAvailable>FALSE</UseHostCompilerIfAvailable>
到第一个属性组(不应该有条件)使Visual Studio始终使用磁盘版本(会稍微减慢Visual Studio的构建速度)。
让您的任务识别Visual Studio
或者让您的构建任务知道IVsMSBuildTaskFileManager
并在更新文件时告诉它。您需要注册your build task in the registry of Visual Studio to flag it as "safe to load"。
答案 1 :(得分:2)
Edit: This does what I describe it to do. Although it doesn't seem that it uses the modified files in the compile process. This is still good reference if someone needs to run a task early on in the entire build process but doesn't want them executing when the project file is loaded. I will come back and edit if I find a solution for my specific problem (which is still relevant to this one!)
Original Answer:
So I found the answer while playing around with information from jessehouwing's answer. Here is the code I used and I will follow with an explanation.
<PropertyGroup>
<ResolveAssemblyReferencesDependsOn>
SetFirstTimeLoading;
$(ResolveAssemblyReferencesDependsOn);
</ResolveAssemblyReferencesDependsOn>
<CompileDependsOn>
RunCustomTask;
$(CompileDependsOn);
</CompileDependsOn>
</PropertyGroup>
<Target Name="SetFirstTimeLoading">
<PropertyGroup>
<FirstTimeLoading Condition=" '$(FirstTimeLoading)' == '' ">false</FirstTimeLoading>
</PropertyGroup>
</Target>
<UsingTask TaskName="MyCustomTask" AssemblyFile="path\to\task" />
<Target Name="RunCustomTask" Condition=" '$(FirstTimeLoading)' == 'false' ">
<MyCustomTask/>
</Target>
I have two targets here. The bottom one is the task I need to run. The second is setting a custom property, SetFirstTimeLoading
, to false
.
RunCustomTask
will run before compiling because it is listed in the CompileDependsOn
.
SetFirstTimeLoading
will run after Compile
but also before ResolveAssemblyReferences
because it is listed in the ResolveAssemblyReferencesDependsOn
.
So because of this, I can have a conditional in my RunCustomTask
target that will see if the FirstTimeLoading
property has been set to false
. This is set the first time the project file is loaded. So any subsequent time the my tasks are run (whenever I build in visual studio), RunCustomTask
's conditional will always evaluate to true
and will run MyCustomTask
.