Visual Studio重建未修改的项目


71

因此,正如标题所示,我现在有一个VS2010解决方案,其中包含约50个项目。如果我更改了没有引用的“顶级”项目,那么VS仍然会重建所有50个项目。我正在运行没有任何附加组件的Visual Studio 2010 Ultimate。我正在使用ILMerge将所有项目合并到一个文件中。

我已经通过检查较低级别的dll的时间戳进行了验证,即使它们的代码未被触及,它们也确实已被重建。

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

Visual Studio 2008不断重建

Visual Studio不断构建所有内容

我的解决方案中出现奇怪的VS2010构建故障

在Visual Studio中重建C#项目的原因

但是它们中的大多数只是提供有关卸载项目的建议,以加快构建时间,但没有针对修复的具体建议。我试图弄清楚为什么VS认为这些依赖项目在不使用时需要重新构建并进行修复。

我已启用“工具>选项>项目和解决方案>构建并运行>仅在运行时构建启动项目和依赖项”,但没有任何效果。

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

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

添加

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

最低的项目称为B,没有引用任何其他项目。下一个项目A仅引用B。因此,一旦我在项目中添加了所需的.NET和外部程序集引用,就可以构建解决方案。

然后,我有了新的WinForm项目参考A,并进行了完整构建。因此,参考链为:

WinForm- > A- > B

然后,我修改WinForm 并进行了标准构建(F6)。和以前一样,Visual Studio重建了所有三个项目。

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

BResources.resxB添加Resources.Designer.cs回项目B(但将引用的代码注释掉,以便没有任何资源的使用)将重新引入完整的构建行为。

为了查看我的资源文件是否损坏,我再次删除了它们,然后创建了一个新文件(通过Project Properties-> Resources),并重新添加了与以前相同的资源,它是一个Excel文件。使用此设置,仍将进行完全重建。

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

似乎仅将资源文件添加到(.NET 3.5)项目中,将导致Visual Studio 2010始终重建该项目。这是错误还是预期/预期的行为?

再次感谢大家!


您可以尝试直接使用msbuild构建它并查看它是否仍然发生吗
Daniel Powell

我的理解是VS会调用msbuild(并且一个项目基本上是msbuild脚本stackoverflow.com/questions/1497344/…),所以我不确定这会改变任何东西。我怀疑我最终将重新创建相同的构建脚本,然后从命令行运行该脚本。是否有某种方式可以直接运行msbuild?也许有某种方法可以找出为什么msbuild认为需要重建项目?
马特·克莱因

您正在建造还是重建?
Ryan Byrne

1
普通建筑物(F6),有时仅投影建筑物(Shift-F6)。两者都表现出相同的行为,尽管“仅项目”构建的重建项目的范围仅限于当前项目的直接和间接依赖关系。
马特·克莱因

@MattKlein是的,我有一种VS确实在内部运行msbuild的感觉,但也许它调用它的方式有所不同,您可以通过执行“ msbuild mysol.sln”从命令行通过msbuild sln文件
Daniel Powell

Answers:


134

打开工具-选项,选择项目和解决方案-生成并在树中运行,然后将“ MSBuild项目生成输出详细程度”设置为“诊断”。这将输出构建项目的原因,即

项目“ ReferencedProject”不是最新的。项目项“ c:\ some.xml”的“复制到输出目录”属性设置为“始终复制”。

要么

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

在这种情况下,解决方法是仅在更新时才复制some.xml。

构建前和构建后事件也可以触发构建。


28
我相信这是最好的答案,因为它使您真正了解导致重复构建的原因,而不仅仅是猜测或试验。
Mark Meuer

很高兴知道!我一直在徘徊,为什么一个项目重建也会重建所有引用的项目。诊断日志解释:'Target“ CleanReferencedProjects:(TargetId:8)”':)
FrankyHollywood

1
谢谢,这正是我所需要的。在我的情况下,事实证明,常量构建是由设置为“始终复制”的.ico文件触发的。
Ryan Lundy

这个答案实际上非常有帮助。+1
Al Kepp '18


17

当项目的文件实际上不存在时,就会发生这种情况。
该项目无法确定文件是否已更改(因为它不存在),因此可以重新生成。

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


这也是我的问题,但是在我的情况下,由于该文件最近被删除,它旁边有一个可扩展的箭头。因此,您可能需要更加仔细地查找才能找到导致重新链接的已删除文件。
Malvineous

如果我有70亿个文件怎么办?
桑德拉(Sandra K)

1
您可以创建一个覆盖项目文件或.filter文件的小脚本/程序,并检查引用的文件是否存在。
Yochai Timmer

17

虽然我认为这不是解决办法,但这是一种适合我情况的解决方法...

我最初有50个项目,其中约有5个包含一个Resources部分。这些项目将始终被重建,因此它们所依赖的任何内容也将被重建。这5个项目之一是“基本”级别的库,其他48个项目都引用了该库,因此即使不需要它,我的项目中的96%也会每次都被重建。

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

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

最后,在我的“顶级”项目中,没有引用任何内容(以及该exe的实际构建位置以及我的合成根目录的存在),我引用了“ Resources”项目,将DI连接起来,然后我们走了。

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

同样,这不是一个很好的解决方法,但是每次构建需要大约3分钟才能构建48个项目,因此我每天不必要的重建损失了30到90分钟。重构花费了一段时间,但我认为这是一笔不错的投资。

这是一个简化图。需要注意的是,从依赖Main.exeProj1Proj2不以减少混乱中。

解决方案图

通过这种设计,我可以进行Proj1Proj2不进行完全重建的构建,因为它们对Resources部分没有任何依赖性。只Main知道Resources实现。


9

我在VS 2015中遇到了同样的问题。

对我来说,诀窍是:

  1. 一个项目正在引用自己在其他项目箱中的副本(魔术,是的)。切换到诊断构建输出(在构建选项中)然后尝试从项目层次结构的顶部逐个构建项目时,会发现这种东西-如果您看到重建的项目,即使没有任何更改,也看到了参考。
  2. 我已将所有项目中的所有“始终复制”文件更改为“如果更新则复制”。基本上,在所有.csproj文件中替换<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  3. 然后,我一直在描述禁用NTFS隧道条与此PowerShell脚本:

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

在那之后,我需要进行重建,现在看来,它可以正常工作。


有没有一种快速的方法(例如,我可以搜索某些特定的文本)?我在VS 2015中面临相同的问题,并且我有一个很大的解决方案文件(包括一些我不被修改的项目,因为它们不属于我)。
EJoshuaS-恢复莫妮卡

4

在我的情况下,罪魁祸首是将引用的dll的“复制本地”设置设置为true,将“复制到输出目录”设置为文件设置为“始终复制”。



1

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

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

此处的解决方法是启用调试符号并让该文件生成,然后再次禁用设置而不删除PDB文件。


在使用源代码管理的团队中,此选项将如何扩展?您是否可以将PDB文件签入源文件(听起来不好)?否则,每当有人重新获得项目时,他们都需要执行此手动步骤。
julealgon

@julealgon:不知道了:/
user541686

1

我遇到了同样的问题,事实证明它与几个项目有关,这些项目在其自己的输出目录中具有对dll的本地复制副本。

找到这一点的关键是为构建输出设置了诊断输出,而且还知道要在日志中查找什么。搜索:“不最新”是关键。


0

这是VS2010始终重建解决方案的答案

通过更改项目文件,清理解决方案,手动删除所有bin文件夹,重新启动Visual Studio并重建所有内容,可以解决此问题。


我不确定“更改项目文件”的含义,但是我给其余部分打了一下,没有任何效果。似乎它可能与资源文件有关(请参阅问题的附加信息)
Matt Klein

0

根据您的观察,听起来您有一个项目以不明显的方式表达了对其他项目的依赖性。孤立的依赖项可能会保留在项目文件中,而不会在UI中显示。在文本编辑器中打开项目文件后,您是否浏览过该文件?检查解决方案构建依赖关系?

如果您什么都看不到,请尝试从头开始重新创建一个项目,以查看新项目是否出现相同的问题。如果清理项目正确构建,您将知道在某个地方表达了不需要的依赖项。据我所知,这些文件必须位于项目文件或解决方案文件中,除非您有makefile文件或其他异常的构建步骤。


经过一些广泛的研究,似乎Resources.resx是造成这种现象的原因。我在问题中添加了信息以描述我的实验。
Matt Klein

从您的新信息尚不清楚将.resx文件添加到哪个项目。无论如何,在测试时要小心,您要在测试之间手动删除所有由构建创建的文件夹,以确保以前的剩余文件不会影响以后的测试。
Owen Wengerd

结果很好奇,但是很遗憾,我没有其他要添加的东西,除非我会继续将问题缩小到最低限度(只有两个项目,而不是三个,只有新的未修改的向导创建的项目,对项目的更改要求最小。重现问题等),然后查看其他人是否可以使用相同的项目文件重现该问题。如果可以,请通过Microsoft Connect提交错误报告。
Owen Wengerd

对于未包括我正在调整的项目,我深表歉意。我已经更新了该语句,以表明我正在修改最低(B)项目的资源文件。我将继续探索,因为我每天可能会浪费1个小时等待不必要的重建。
Matt Klein

0

我也遇到过同样的问题。我发现它来自一些已删除的文件。从项目中删除文件后,问题就消失了。问候。


0

对于此类构建问题,将MSBuild输出详细程度设置为“诊断”确实是必要的第一步。在大多数情况下,所陈述的重建原因足以采取行动,但有时MSBuild会错误地声称某些文件已修改且需要复制。

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


0

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

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

find . -exec touch {} \;

0

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

就我而言,问题在于解决方案中的所有项目都具有相同的中间输出路径(obj)。包含XAML的所有项目都将生成文件GeneratedInternalTypeHelper.cs。直到Visual Studio 2015,构建过程显然都没有检查此文件的文件日期,因此没有发生任何问题。使用VS2017,将检查此文件的文件日期,并且由于构建过程中的更高版本的项目将覆盖它(具有相同的内容),因此较早版本的项目将重新构建,并无限触发重新构建更高版本的项目。

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


0

就我而言(混合的C#,C ++ / CLI和本机C ++解决方案),即使没有任何更改,某些C ++项目也正在重新链接。我花了很长时间试图找出正在发生的事情。最后,我从“命令行”选项得出结论,PDB输出路径(选项/ Fd)无法处理文件夹设置$(IntDir)。我删除了它-一个空值将正确地执行默认设置-并且我的问题消失了。


0

正如其他人所注意到的,可能的原因是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
}

0

对于.Net Core项目,以上所有解决方案均不起作用。我找到了解决方案。如果您使用的是Visual Studio 2019:

  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在生成输出的最后一个字符串中实现。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.