VisualStudio 重新生成未修改的项目

因此,正如标题所示,我有一个 VS2010解决方案,其中包含约50个项目。如果我对一个没有任何参考的“顶级”项目进行更改,那么 VS 仍然会重新构建所有50个项目。我正在运行 VisualStudio2010终极版,没有任何附加组件。我使用 ILMerge 将所有的项目合并到一个文件中。

我通过检查较低级别 dls 的时间戳来验证这一点,并查看它们确实是重新构建的,即使它们的代码没有被修改。

我已经阅读了所有的回复和评论:

VisualStudio2008继续重新生成

视觉工作室一直在建造一切

奇怪的 VS2010建设故障发生在我的解决方案

在 Visual Studio 中重新生成 C # 项目的原因

但他们中的大多数只是提供了关于卸载项目的建议,以加快建设时间,但没有具体的解决方案。我试图弄明白为什么 VS 认为这些依赖项目需要重建,而实际上它们并不需要,并且需要修复它们。

我打开了“工具 > 选项 > 项目和解决方案 > 建立和运行 > 只在运行时建立启动项目和依赖”,但是没有效果。

另外,如果我只是重新构建一个只有8个(in)直接依赖项的“中级”项目,那么即使没有调用 ILMerge 并且没有修改任何依赖项目,它仍然会构建所有8个项目。

感谢大家提供的任何见解。

补充

为了测试一些建议,我从头开始创建了一个新的 WinForms 项目。然后,我在该解决方案中创建了两个新项目。我将我的两个“最低级别”项目中的所有代码和资源(不是项目文件)复制到两个全新的项目中(我将文件和文件夹从资源管理器中删除到 Visual Studio 中的项目中)。

最低的项目,让我们称之为 B,没有参考任何其他项目。下一个项目,A,只引用了 B。所以一旦我添加了所需的。NET 和外部程序集引用到项目,然后将生成解决方案。

然后我有了我的新 WinForm 项目参考 A,并做了一个完整的构建,所以参考链是:

WinForm -> A-> < strong > B

然后,我修改了 WinForm 只有并做了一个标准的构建(F6)。

在对项目 B中的源文件进行了一些系统的删除之后,我发现如果我删除了我的 Resources.Designer.csResources.resx(并且注释掉了使用这些资源的 .Properties.Resources对象的代码) ,那么对 WinForm的修改将不再重建整个解决方案,而只会重建 WinForm

Resources.resxResources.Designer.cs添加回项目 B(但是将引用的代码注释掉,这样就不会有任何东西利用这些资源)将重新引入完整的构建行为。

为了查看资源文件是否损坏,我再次删除了它们,然后创建了一个新的(通过 Project Properties-> Resources) ,并重新添加了与之前相同的资源,即一个 Excel 文件。有了这个设置,完整的重建仍然会发生。

然后删除了单个资源,但是将资源文件保留在项目 B中。即使没有添加资源,但是资源文件仍然在项目中,也会发生完全(不需要的)重建。

似乎只需将一个资源文件添加到(。NET 3.5)项目将导致 VisualStudio2010始终重新生成该项目。这是一个错误还是预期的/预期的行为?

再次感谢大家!

40608 次浏览

这是来自 VS2010总是重建解决方案?的答案

这个问题可以通过更改项目文件、清理解决方案、, 手动删除所有 bin 文件夹,重新启动 VisualStudio 和 重建一切。

根据您的观察,似乎您的项目以一种不明显的方式表达了对其他项目的依赖。孤立的依赖项可以保留在项目文件中,而不会在 UI 中显示出来。在文本编辑器中打开一个行为不当的项目文件后,您是否查看了它?检查解决方案生成依赖项?

如果您无法发现任何问题,请尝试从头开始重新创建一个项目,以查看新项目是否存在同样的问题。如果干净的项目生成正确,您将知道在某处表达了不需要的依赖项。据我所知,这些必须在项目文件或解决方案文件中,除非您有 makefile 或其他不寻常的构建步骤。

虽然我不认为这是一个解决方案,这是一个变通办法,已经为我的情况..。

我最初有大约50个项目中的5个包含 Resources部分。这些项目将始终得到重建,因此它们所依赖的任何东西也将得到重建。这5个项目中有一个是“基础”级别的库,其他48个项目都参考了这个库,因此即使我的项目不需要它,它也会每次重建96% 。

我的解决方案是使用依赖注入、接口和一个专门的“资源”项目。我没有让这5个项目引用它们自己的 Resources对象,而是在每个项目中创建了一个接口来提供所需的资源。然后,需要这些资源的类将要求在构造函数(构造函数注入)中创建时传入该接口。

然后,我创建了一个单独的“ Resources”项目,其中像往常一样有一个实际的 Resources 部分。该项目只包含资源本身,以及通过接口提供这些资源所需的每个接口的类。该项目将引用具有资源依赖关系的每个其他项目,并实现该项目所需的接口。

最后,在我的“顶级”项目中,没有任何引用(也没有任何引用 exe 实际构建的地方,也没有引用我的组合根目录) ,我引用了“资源”项目,连接了 DI,然后我们就开始了。

这意味着每次只有两个项目(“资源”和“顶层”)将被重新构建,如果我进行部分构建(Shift-F6) ,那么它们根本不会被重新构建。

再次强调,这不是一项很好的工作,但是每次构建大约需要3分钟时间,就有48个项目正在构建,所以我每天浪费30到90分钟进行不必要的重新构建。花了一段时间重构,但我认为这是一个很好的投资。

下面是一个简化的图表。注意,为了减少混乱,没有显示从 Main.exeProj1Proj2的依赖关系。

Diagram of solution

通过这种设计,我可以构建 Proj1Proj2而不触发完全重建,因为它们不依赖于 Resources部分。只有 Main知道 Resources的实现。

当一个项目有一个并不真正存在的文件时,就会发生这种情况。
项目无法确定文件是否已经更改(因为它不在那里) ,所以需要重新构建。

只需查看项目中的所有文件,然后搜索附近没有可展开箭头的文件。

我和你也有同样的问题。 我发现它来自一些被删除的文件。 当我从我的项目中删除文件时,问题就消失了。 问候。

打开工具-选项,选择项目和解决方案-在树中构建和运行,然后将“ MSBuild 项目构建输出详细信息”设置为“诊断”。 这将输出建立一个项目的理由,即。

项目“ ReferencedProject”不是最新的 “ c: some. xml”将“ Copy to Output Directory”属性设置为“ Copy” 一直都是。

或者

项目“ MyProject”不是最新的。输入文件 “ c: ReferencedProject.dll”在输出文件之后被修改 C: MyProject. pdb.

在这种情况下,修复方法是仅在较新的情况下复制 some. xml。

生成前和生成后事件也可以触发生成。

对于这类构建问题,将 MSBuild 输出冗长设置为“诊断”确实是必要的第一步。大多数时候,重新构建的原因已经足够采取行动了,但是偶尔 MSBuild 会错误地声称某些文件被修改并需要复制。

如果是这种情况,您需要禁用 NTFS 隧道,或者将您的输出文件夹复制到一个新位置。这里是更多的文字。

在我的案例中,罪魁祸首是将引用的 dll 设置为 true 的“ CopyLocal”设置和将文件设置为 Copyalways 的“ CopytoOutputDirectory”设置。

我在 VS 2015年也遇到过同样的问题。

我的诀窍是:

  1. 一个项目在其他项目中引用自己的副本(魔术,是的)。当切换到诊断构建输出(在构建选项中) ,然后尝试从项目层次结构的顶部一个接一个地构建项目时,可以发现这种情况——如果你看到重新构建的项目,即使什么都没有改变,也可以查看它的引用。
  2. 我已经将所有项目中的所有“ copy Always”文件改为“ copy if new” 到 <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  3. 然后,我使用这个 Powershell 脚本禁用了 这个文章中描述的 NTFS 隧道:

New-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "MaximumTunnelEntries" -Value 0 -PropertyType "DWord"

之后我需要重建,现在看起来还不错。

另一个经常发生的问题是,当解决方案中的某个项目有一个修改后的戳记时。如果您将时钟向前调,然后将时钟设置为正确的时间,就会发生这种情况。我在安装 Linux 时发生了这种情况。

在这种情况下,您可以使用 git bash (是的,在 Windows 中)递归地触摸所有文件:

find . -exec touch {} \;

通过增加构建日志的冗长度,我终于找到了另一个难以找到的罪魁祸首。

在某些情况下,MSBuild 在输出文件夹中查找 vc120.pdb,如果该文件不存在,它将重新生成整个项目。这发生在 即使已禁用调试符号生成

这里的解决办法是启用调试符号,让这个文件生成,然后再次禁用设置 没有删除 PDB 文件。

在从 Visual Studio 2015升级到2017时,我遇到了 Visual Studio 重建项目的问题,为了那些可能遇到类似问题的人的利益,我添加了这个答案,因为它似乎没有在任何地方被记录。

在我的例子中,问题是解决方案中的所有项目都有相同的中间输出路径(obj)。文件 generatedinternaltypehelper.cs 由所有包含 XAML 的项目生成。直到 VisualStudio2015,生成过程显然没有检查该文件的文件日期,因此没有发生任何问题。使用 VS2017会检查该文件的文件日期,并且因为构建过程中的后续项目将覆盖该文件(使用相同的内容) ,所以前面的项目将重新构建,重新触发后面的构建,无限期地重新构建。

在这种情况下,解决方案是确保所有项目都有不同的中间输出目录,这将使问题消失。

我遇到过同样的问题,结果发现它与两个项目有关,这两个项目在它们自己的输出目录中有一个对 dll 的复制本地引用。

找到这一点的关键是为构建输出设置诊断输出,但也要知道在日志中查找什么。搜索: ‘ 不是最新的’是关键。

在我的例子中(混合 C # 、 C + +/CLI 和原生 C + + 解决方案) ,一些 C + + 项目被重新链接,即使没有任何改变。我花了很长时间想弄清楚到底发生了什么。最后,我从“ Command Line”选项中得出结论,PDB 输出路径(option/Fd)不能处理文件夹设置 $(IntDir)。我删除了它——一个空值将正确执行默认值——我的问题就解决了。

正如其他人所注意到的,一个可能的原因是 CopyToOutputDirectory 被设置为 Always。通过应用下面的 PowerShell 脚本,可以在所有项目文件中同时解决这个问题:

$folder = "C:\My\Solution\Folder"
$csvFiles = Get-ChildItem $folder *.csproj -rec
foreach ($file in $csvFiles)
{
(Get-Content $file.PSPath -Encoding UTF8 -Raw) |
Foreach-Object { $_ -replace "<CopyToOutputDirectory>Always</CopyToOutputDirectory>", "<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>" } |
Set-Content $file.PSPath -Encoding UTF8 -NoNewline
}

对于.Net 核心项目,以上所有解决方案都无法工作。 我已经找到了解决方案。如果您正在使用 VisualStudio2019:

  1. 构建解决方案两次
  2. 打开 Tools-> Options-> Projects and Solutions-> SDK-Style Projects-> Logging Level-> Verbose
  3. 清除输出窗口
  4. 构建您的初始项目
  5. 检查输出窗口。所有字符串以 FastUpToDate开头
  6. 您将发现一些使您的项目无法更新的项目项。
  7. 修复这些问题,然后从步骤1再试一次。如果您的修复是正确的,您将在构建输出的最后一个字符串中实现 Build: 0 succeeded, 0 failed, {n} up-to-date, 0 skipped

不存在的文件是一个问题,显然文件也不会产生任何输出。如果在静态库中有一个资源文件,就会发生这种情况。(C + +)