Visual Studio 添加始终运行的预构建事件(C# 项目)

34
在我的项目中,我正在运行一个外部工具来更新一些二进制文件。这些文件被包含在项目中作为“内容”。
目前,该工具被设置为在C#项目属性的“预构建事件”中运行。不幸的是,此事件仅在项目过时时执行,这不是我所需要的。
我通过始终在项目上使用“重新生成”而不是“生成”来解决这个问题,但这很繁琐和缓慢。
我需要始终执行此工具,无论项目是否过时。实际上,在MSBuild确定项目是否已经更新之前就需要执行此工具,因为该工具修改了项目中包含的某些文件,从而影响到更新检查结果。
有没有合适的方法来做到这一点?

1
不,当项目加载到集成开发环境中时修改它们是行不通的。肯定有更好的方法,你的问题没有帮助我们帮助你。 - Hans Passant
3
@HansPassant 或许我在问题上过度设计了。归根结底,问题是:有没有一种方法可以在构建之前 始终 运行一个命令? - kaalus
1
对于C++项目,您可以使用带有“BeforeTargets =”BuildGenerateSources“属性的目标来完成此操作;对于C#,您可以做类似的事情,只需找出在构建中调用的众多目标中要使用哪个BeforeTargets属性。运行详细构建并检查输出或开始查看Microsoft.CSharp.targets等文件。但是正如Hans所说:结果可能不是您所期望的。 - stijn
当在 Visual Studio 的鼻子底下更改磁盘上的源代码时,会导致各种有趣的行为,您需要关闭 HostCompiler 服务(这会稍微减慢 Visual Studio 的速度):http://blog.jessehouwing.nl/2012/06/just-in-time-updating-of-source-files.html - jessehouwing
1
对于C#,它将是“BuildDependsOn”组,https://msdn.microsoft.com/en-us/library/ms366724.aspx,或者您可以扩展解决方案本身:https://dev59.com/33E95IYBdhLWcg3wd9xK#5720489(请参见第二个答案,被接受的答案不是您想要的)。 - jessehouwing
5个回答

60

这是解决方案。在您的项目文件中定义此属性:

<PropertyGroup>
    <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
</PropertyGroup> 

PreBuildStep会在每次执行时都运行,无论项目是否是最新的。

看起来Visual Studio绕过了MSBuild的正常更新检查,并使用某种定制检查来提高速度,但它具有破坏自定义构建目标的副作用。


17
更准确地说,它必须是<PropertyGroup> <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck> </PropertyGroup> - Maghoumi
2
为什么被采纳的答案不是页面上的第一个答案? - Dave Lawrence
8
即使没有任何更改,这也会触发构建。 - vip32

10

在项目级别上,您有三个选项:

1)预构建动作

<PropertyGroup>
  <PreBuildEvent>notepad.exe Foo.txt</PreBuildEvent>
</PropertyGroup>

2)正常的BeforeBuild目标

<Target Name="BeforeBuild">
  <Exec Command="notepad.exe Foo.txt" />
</Target>

3) "attached" to "Build" target (like stijn suggested)

3)“附加”到“Build”目标(就像stijn建议的那样)
<Target Name="BeforeBuild2" BeforeTargets="Build">
  <Exec Command="notepad.exe Foo.txt" />
</Target>

实际上,在构建的情况下,这个解决方案是行不通的,因为DependsOnTargets是在BeforeTargets之前执行的。而真正的(CoreBuild)就坐落在DependsOnTargets中:)这就是为什么他们发明了“BeforeBuild”目标;)


在两种情况下,VS都会检查是否有更改(文件是否是最新的)。如果没有任何更改,为什么您甚至想运行外部程序呢?如果此程序对文件(例如“content”)进行操作,则msbuild和VS应将文件识别为过时的并处理构建。


不幸的是,IDE(Visual Studio)有自己的处理msbuild项目的方法。主要机制是相同的,但当确定要构建哪个项目或以何种顺序构建时... VS的操作完全不同。

您可以使用外部工具并针对您的解决方案或项目运行“msbuild”。这也将编译“正确的方式”,二进制文件不会有所不同,但您将拥有MsBuild的全部功能和潜力。


1
我需要运行外部程序,因为它可以将大量文件处理成单个二进制文件。将所有这些文件添加到Visual Studio项目中是不可行的,因此它们不在项目中。MSBuild对它们一无所知。外部工具有自己的最新检查机制,用于检查这些文件是否需要处理,但首先需要运行它,而VS不想合作。这是否太过分了... - kaalus
1
你真的应该添加一个#4示例,其中BeforeTargets="BeforeBuild" .. 这可以帮助很多。 - Aaron Hudon
注意,如果存在两个具有相同名称的目标,则只会使用后者。因此,由于许多项目已经具有“BeforeBuild”目标,这可能会导致大量隐式问题。最好发明自己命名的目标并将其配备BeforeTargets="Build"特性。 - Yury Schkatula

2

还有一个额外的预构建事件没有在这里讨论。通常,代码分析器使用它来检查是否通过NuGet下载了代码分析器。

因此,如果您想在代码分析器之前执行某些操作,则需要使用该目标。

您只需在.csproj文件的节点下添加节点:

<Target Name="DownloadNugetPackages" BeforeTargets="PrepareForBuild">
    <Exec Command="notepad.exe Foo.txt"/>
</Target>

PrepareForBuild事件将在预先构建事件之前运行。


1
没有一种解决方案适用于我在使用Visual Studio for Mac时的情况。 我想在构建项目之前运行bash脚本,但由于我正在使用Xamarin,有些事情变得混乱了。 我尝试了所有不同类型的目标,甚至尝试了项目选项中的CustomCommands,但仍然会出现关于MSbuild自动运行或在构建之前未真正运行的问题。
您可以在一个在主项目之前编译的单独项目中运行PreBuild事件。
1.创建一个新项目,并将其命名为“PreBuildEvent”。 2.为每个属性组/构建配置将您的MSbuild目标/命令添加到此新的PreBuildEvent.csproj文件中,如上所示。 3.在您最初要进行PreBuild工作的项目中,添加对此新项目的引用。 4.这个新项目将首先构建,执行任何PreBuild事件,一旦构建了此项目,它就会启动原始项目的构建。 这是因为当您添加对项目的引用时,Visual Studio会确保按正确顺序构建它们。

0
我的解决方案是创建另一个项目(配置Makefile)并将该项目设置为BuildDependancy。
这样可以避免修改预构建步骤的运行方式,并且如果需要,您可以隔离生成二进制文件以便与构建过程的其他部分进行重建。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接