Visual Studio erstellt unveränderte Projekte neu

71

Wie der Titel schon sagt, habe ich gerade eine VS2010-Lösung mit ~ 50 Projekten. Wenn ich ein "Top-Level" -Projekt ändere, auf das nichts verweist, erstellt VS immer noch alle 50 Projekte neu. Ich verwende Visual Studio 2010 Ultimate ohne Add-Ons. Ich verwende ILMerge, um alle Projekte in einer einzigen Datei zu konsolidieren.

Ich habe dies überprüft, indem ich die Zeitstempel der DLLs der unteren Ebene überprüft habe und festgestellt habe, dass sie tatsächlich neu erstellt wurden, obwohl ihr Code nicht berührt wurde.

Ich habe alle Antworten und Kommentare gelesen für:

Visual Studio 2008 wird ständig neu erstellt

Visual Studio baut alles weiter

In meiner Lösung tritt ein seltsamer VS2010-Build-Fehler auf

Gründe für die Neuerstellung von C # -Projekten in Visual Studio

Die meisten von ihnen bieten jedoch nur Vorschläge zum Entladen von Projekten an, um die Bauzeiten zu verkürzen, aber nichts Konkretes für eine Lösung. Ich versuche herauszufinden, warum VS der Meinung ist, dass diese abhängigen Projekte neu erstellt werden müssen, wenn dies nicht der Fall ist, und behebe sie.

Ich habe "Extras> Optionen> Projekte und Lösungen> Erstellen und Ausführen> Nur Startprojekte und Abhängigkeiten beim Ausführen erstellen" aktiviert, aber ohne Auswirkung.

Wenn ich nur ein "Mid-Level" -Projekt neu erstelle, das nur 8 (in) direkte Abhängigkeiten aufweist, werden weiterhin alle 8 Projekte erstellt, obwohl ILMerge nicht aufgerufen wird und keines der abhängigen Projekte geändert wurde.

Vielen Dank an alle für jeden Einblick, den Sie möglicherweise gewähren können.

Hinzugefügt

Um einige der Vorschläge zu testen, habe ich ein neues WinForms-Projekt von Grund auf neu erstellt. Ich habe dann zwei neue Projekte in dieser Lösung erstellt. Ich habe den gesamten Code und die Ressourcen (keine Projektdatei) aus meinen beiden Projekten auf der untersten Ebene in die beiden brandneuen Projekte kopiert (dazu habe ich die Dateien und Ordner aus dem Explorer in Visual Studio auf das Projekt abgelegt).

Das niedrigste Projekt, nennen wir es B , hat kein anderes Projekt referenziert. Das nächste Projekt, A , verwiesen B nur. Sobald ich die erforderlichen .NET- und externen Assemblyreferenzen zu den Projekten hinzugefügt habe, wird die Lösung erstellt.

Ich hatte dann meine neue WinForm-Projektreferenz A und habe einen vollständigen Build durchgeführt. Die Ref-Kette lautet also:

WinForm -> A -> B.

Ich habe dann nur WinForm geändert und einen Standard-Build (F6) durchgeführt. Nach wie vor hat Visual Studio alle drei Projekte neu erstellt.

Nach einer systematischen Eliminierung der Quelldateien in Projekt B stellte ich fest, dass eine Änderung von WinForm nicht mehr die gesamte Lösung neu erstellen und nur neu erstellen würde , wenn ich meine Resources.Designer.csund Resources.resx(und den Code auskommentierte, der das .Properties.ResourcesObjekt dieser Ressourcen verwendete) WinForm .

Das Hinzufügen von Resources.resxund Resources.Designer.cszurück zu Projekt B (aber das Auskommentieren des Codes, auf den verwiesen wird, damit die Ressourcen nicht genutzt werden) würde das vollständige Build-Verhalten wieder einführen.

Um festzustellen, ob meine Ressourcendateien möglicherweise beschädigt waren, habe ich sie erneut gelöscht und dann eine neue erstellt (über Projekteigenschaften -> Ressourcen) und dieselbe Ressource wie zuvor erneut hinzugefügt, bei der es sich um eine einzelne Excel-Datei handelte. Mit diesem Setup würde die vollständige Neuerstellung weiterhin stattfinden.

Ich habe dann die einzelne Ressource entfernt, aber die Ressourcendatei in Projekt B belassen . Selbst wenn keine Ressourcen hinzugefügt werden, sich die Ressourcendatei jedoch noch im Projekt befindet, wird die vollständige (nicht benötigte) Neuerstellung durchgeführt.

Es scheint, dass nur das Hinzufügen einer Ressourcendatei zu einem (.NET 3.5) -Projekt dazu führt, dass Visual Studio 2010 dieses Projekt immer neu erstellt. Ist dies ein Fehler oder ein beabsichtigtes / erwartetes Verhalten?

Nochmals vielen Dank!

Matt Klein
quelle
können Sie versuchen, es mit msbuild direkt zu erstellen und zu sehen, ob es immer noch passiert
Daniel Powell
Nach meinem Verständnis ruft VS msbuild auf (und ein Projekt ist im Grunde ein msbuild-Skript stackoverflow.com/questions/1497344/… ), daher bin ich mir nicht sicher, ob dies etwas ändern würde. Ich vermute, ich würde am Ende einfach dasselbe Build-Skript neu erstellen und es dann über die Befehlszeile ausführen. Gibt es eine Möglichkeit, wie msbuild direkt ausgeführt werden kann? Oder vielleicht eine Möglichkeit herauszufinden, warum msbuild der Meinung ist, dass die Projekte neu erstellt werden müssen?
Matt Klein
Bauen oder bauen Sie wieder?
Ryan Byrne
1
Normales Gebäude (F6) und manchmal nur Projektgebäude (Umschalt-F6). Beide weisen das gleiche Verhalten auf, obwohl der Umfang der neu erstellten Projekte des "Nur Projekt erstellen" auf die direkten und indirekten Abhängigkeiten des aktuellen Projekts beschränkt ist.
Matt Klein
@MattKlein Ja, ich habe das Gefühl, dass VS msbuild intern ausführt, aber vielleicht gibt es etwas an der Art und Weise, wie es aufgerufen wird, das möglicherweise anders ist. Sie können Ihre sln-Datei über die Befehlszeile msbuilden, indem Sie "msbuild mysol.sln" ausführen
Daniel Powell

Antworten:

134

Öffnen Sie Extras - Optionen, wählen Sie Projekte und Lösungen - Erstellen und Ausführen in der Baumstruktur aus und setzen Sie "Ausführlichkeit für die Ausgabe von MSBuild-Projekterstellungen" auf "Diagnose". Dies gibt den Grund für das Erstellen eines Projekts aus, d. H.

Das Projekt 'ReferencedProject' ist nicht aktuell. Für das Projektelement 'c: \ some.xml' wurde das Attribut 'In Ausgabeverzeichnis kopieren' auf 'Immer kopieren' gesetzt.

oder

Das Projekt 'MyProject' ist nicht aktuell. Die Eingabedatei 'c: \ ReferencedProject.dll' wird nach der Ausgabedatei 'c: \ MyProject.pdb' geändert.

In diesem Fall besteht das Update darin, some.xml nur zu kopieren, wenn es neuer ist.

Ereignisse vor und nach dem Build können ebenfalls den Build auslösen.

user3285954
quelle
28
Ich glaube, dies ist die beste Antwort, da Sie damit tatsächlich verstehen, warum sich die Builds wiederholen, anstatt nur zu raten oder zu experimentieren.
Mark Meuer
Gut zu wissen! Ich habe gewandert, warum bei einer Projektwiederherstellung auch alle referenzierten Projekte neu erstellt werden. Die Diagnoseprotokollierung erklärt: 'Ziel "CleanReferencedProjects: (TargetId: 8)"' :)
FrankyHollywood
1
Danke, das ist genau das, was ich brauchte. In meinem Fall stellte sich heraus, dass das konstante Erstellen durch eine .ico-Datei ausgelöst wurde, die auf "Immer kopieren" gesetzt war.
Ryan Lundy
Diese Antwort ist eigentlich sehr hilfreich. +1
Al Kepp
Ausführlicherer Artikel oz-code.com/blog/…
vinogradniy
17

Dies geschieht, wenn ein Projekt eine Datei hat, die nicht wirklich existiert.
Das Projekt kann nicht feststellen, ob die Datei geändert wurde (weil sie nicht vorhanden ist), sodass sie neu erstellt wird.

Sehen Sie sich einfach alle Dateien im Projekt an und suchen Sie nach der Datei, in der sich kein erweiterbarer Pfeil befindet.

Yochai Timmer
quelle
Dies war auch mein Problem, aber in meinem Fall befand sich daneben ein erweiterbarer Pfeil, da die Datei kürzlich gelöscht wurde. Daher müssen Sie möglicherweise etwas genauer hinschauen, um die gelöschte Datei zu finden, die die erneute Verknüpfung verursacht.
Malvineous
Was ist, wenn ich 7 Milliarden Dateien habe?
Sandra K
1
Sie können ein kleines Skript / Programm erstellen, das die Projektdatei oder die Filterdatei durchläuft, und überprüfen, ob die referenzierten Dateien vorhanden sind.
Yochai Timmer
17

Ich denke zwar nicht, dass dies eine Lösung ist, aber es ist eine Problemumgehung, die für meine Situation funktioniert hat ...

Ich hatte ursprünglich ungefähr 5 von 50 Projekten, die einen ResourcesAbschnitt enthielten . Diese Projekte würden immer wieder aufgebaut und somit würde auch alles, worauf sie angewiesen waren, wieder aufgebaut. Eines dieser 5 Projekte war eine Bibliothek auf "Basis" -Ebene, auf die 48 der anderen Projekte verwiesen, sodass 96% meines Projekts jedes Mal neu erstellt wurden, selbst wenn es nicht benötigt wurde.

Meine Problemumgehung bestand darin, Abhängigkeitsinjektion, Schnittstellen und ein spezielles "Ressourcen" -Projekt zu verwenden. Anstatt diese 5 Projekte auf ihr eigenes ResourcesObjekt verweisen zu lassen , habe ich in jedem Projekt eine Schnittstelle erstellt, die die gewünschten Ressourcen bereitstellt. Für die Klassen, die diese Ressourcen benötigen, muss die Schnittstelle dann während ihrer Erstellung im Konstruktor übergeben werden (Konstruktorinjektion).

Ich habe dann ein separates "Ressourcen" -Projekt erstellt, das wie gewohnt einen tatsächlichen Ressourcenabschnitt hatte. Dieses Projekt enthielt nur die Ressourcen selbst und eine Klasse für jede Schnittstelle, die benötigt wurde, um diese Ressourcen über eine Schnittstelle bereitzustellen. Dieses Projekt würde auf jedes andere Projekt verweisen, das eine Ressourcenabhängigkeit aufweist, und die Schnittstelle implementieren, die das Projekt benötigt.

Schließlich habe ich in meinem "Top Level" -Projekt, auf das sich nichts bezog (und wo die Exe tatsächlich erstellt wurde und meine Kompositionswurzel lebt), auf das "Resources" -Projekt verwiesen, den DI verkabelt und los ging es.

Dies bedeutet, dass jedes Mal nur zwei Projekte (die "Ressourcen" und die "oberste Ebene") neu erstellt werden. Wenn ich einen Teilaufbau durchführe (Shift-F6), werden sie überhaupt nicht neu erstellt.

Wiederum keine großartige Arbeit, aber mit 48 Projekten, die jedes Mal erstellt wurden, wenn ein Build ungefähr 3 Minuten dauerte, verlor ich 30 bis 90 Minuten pro Tag durch unnötige Umbauten. Das Refactor hat eine Weile gedauert, aber ich denke, es war eine gute Investition.

Hier ist ein vereinfachtes Diagramm. Beachten Sie, dass die Abhängigkeiten von Main.exebis Proj1und Proj2nicht angezeigt werden, um die Unordnung zu verringern.

Diagramm der Lösung

Mit diesem Design kann ich einen Build erstellen Proj1oder Proj2ohne einen vollständigen Rebuild auszulösen, da sie keine Abhängigkeiten von einem ResourcesAbschnitt haben. Nur Mainweiß um die ResourcesUmsetzung.

Matt Klein
quelle
9

Ich hatte das gleiche Problem in VS 2015.

Was hat der Trick für mich getan:

  1. Ein Projekt verwies auf eine Kopie in einem anderen Projektfach (Magie, ja). Diese Art von Dingen kann gefunden werden, wenn Sie zur Diagnose-Build-Ausgabe wechseln (in den Build-Optionen) und dann versuchen, Projekte einzeln von der Spitze der Projekthierarchie aus zu erstellen. Wenn Sie das Projekt sehen, das neu erstellt wird, auch wenn nichts geändert wurde, sehen Sie es Verweise.
  2. Ich habe alle "Immer kopieren" -Dateien in allen Projekten in "Kopieren, wenn neuer" geändert. Grundsätzlich in allen CSPROJ Dateien ersetzen <CopyToOutputDirectory>Always</CopyToOutputDirectory> zu<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  3. Dann habe ich das NTFS-Tunneln wie in diesem Artikel beschrieben mit diesem Powershell-Skript deaktiviert:

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

Danach musste ich wieder aufbauen und es scheint für jetzt zu funktionieren.

Michael Logutov
quelle
Gibt es eine schnelle Möglichkeit, dies zu tun (z. B. einen bestimmten Text, den ich durchsuchen kann)? Ich habe in VS 2015 das gleiche Problem und habe eine ziemlich große Lösungsdatei (einschließlich einiger Projekte, die ich nicht ändern darf, weil sie mir nicht "gehören").
EJoshuaS
4

In meinem Fall war der Schuldige die Einstellung "Lokal kopieren" einer referenzierten DLL, die auf "true" gesetzt war, und "In Ausgabeverzeichnis kopieren", wobei eine Datei auf "Immer kopieren" gesetzt wurde.

IAN
quelle
1

Das MSBuild-Team sammelt hier Dokumentation zur Untersuchung von Build-Inkrementalitätsproblemen: https://github.com/Microsoft/MSBuild/wiki/Rebuilding%20when%20nothing%20changed

Kirill Osenkov
quelle
1
Wirklich nützlicher Link. Habe dort auch dein Werkzeug erwähnt, wirklich gute Arbeit daran! Ich werde es wahrscheinlich versuchen, um eine unserer Lösungen zu debuggen.
Julealgon
1

Ich habe endlich einen weiteren Schuldigen gefunden, den ich nur schwer finden konnte, indem ich die Ausführlichkeit des Build-Protokolls erhöhte.

In einigen Fällen sucht MSBuild vc120.pdbim Ausgabeordner. Wenn diese Datei nicht vorhanden ist, wird das gesamte Projekt neu erstellt. Dies tritt auch dann auf , wenn Sie die Debug-Symbolgenerierung deaktiviert haben .

Die Problemumgehung besteht darin, Debug-Symbole zu aktivieren und diese Datei generieren zu lassen. Deaktivieren Sie dann die Einstellung erneut, ohne die PDB-Datei zu löschen.

user541686
quelle
Wie würde sich diese Option in einem Team mit Quellcodeverwaltung skalieren lassen? Würden Sie die PDB-Datei in die Quelle einchecken (das klingt schlecht)? Andernfalls muss jeder, der das Projekt frisch erhält, diesen manuellen Schritt ausführen.
Julealgon
@ Julealgon: keine Ahnung: /
user541686
1

Ich hatte das gleiche Problem und es stellte sich heraus, dass es sich um ein paar Projekte handelte, die einen lokalen Verweis auf eine DLL in ihrem eigenen Ausgabeverzeichnis hatten.

Der Schlüssel, um dies zu finden, bestand darin, die Diagnoseausgabe für die Build-Ausgabe festzulegen, aber auch zu wissen, worauf im Protokoll zu achten ist. Suchen nach: ' nicht aktuell ' war der Schlüssel.

Ademund
quelle
0

Hier ist eine Antwort von VS2010, die Lösung immer neu erstellt?

Dieses Problem wird behoben, indem die Projektdateien geändert, die Lösung bereinigt, alle Papierkorbordner manuell gelöscht, Visual Studio neu gestartet und alles neu erstellt werden.

Ryan Byrne
quelle
Ich bin mir nicht sicher, was "Ändern der Projektdateien" bedeutet, aber ich habe den Rest ohne Wirkung ausprobiert. Es scheint, als ob es sich um eine Ressourcendatei handelt (siehe zusätzliche Informationen zur Frage)
Matt Klein
0

Basierend auf Ihren Beobachtungen klingt es so, als hätten Sie Projekte, die Abhängigkeiten zu anderen Projekten auf eine Weise ausdrücken, die nicht offensichtlich ist. Verwaiste Abhängigkeiten können in Projektdateien verbleiben, ohne in der Benutzeroberfläche angezeigt zu werden. Haben Sie eine sich schlecht verhaltende Projektdatei durchgesehen, nachdem Sie sie in einem Texteditor geöffnet haben? Überprüfte Abhängigkeiten beim Erstellen von Lösungen?

Wenn Sie nichts erkennen können, versuchen Sie, eines Ihrer Projekte von Grund auf neu zu erstellen, um festzustellen, ob das neue Projekt das gleiche Problem aufweist. Wenn das saubere Projekt korrekt erstellt wird, wissen Sie, dass Sie unerwünschte Abhängigkeiten haben, die irgendwo ausgedrückt werden. Soweit ich weiß, müssten sich diese in den Projektdateien oder der Lösungsdatei befinden, es sei denn, Sie haben Makefiles oder andere ungewöhnliche Erstellungsschritte.

Owen Wengerd
quelle
Nach einigen umfangreichen Recherchen scheint Resources.resxes, dass a die Ursache für dieses Verhalten sein könnte. Ich habe meiner Frage Informationen hinzugefügt, um meine Experimente zu beschreiben.
Matt Klein
Aus Ihren neuen Informationen geht nicht hervor, zu welchem ​​Projekt Sie die .resx-Datei hinzugefügt haben. Seien Sie in jedem Fall vorsichtig, wenn Sie testen, dass Sie alle vom Build erstellten Ordner zwischen den Tests manuell entfernen, um sicherzustellen, dass übrig gebliebene Dateien aus früheren Tests keine Auswirkungen auf spätere Tests haben.
Owen Wengerd
Die Ergebnisse sind merkwürdig, aber leider habe ich nichts Neues hinzuzufügen, außer dass ich das Problem weiterhin auf das Nötigste eingrenzen würde (nur zwei statt drei Projekte, nur neue, nicht modifizierte Assistenten erstellten Projekte mit den minimal erforderlichen Änderungen an Reproduzieren Sie das Problem usw.) und prüfen Sie, ob jemand anderes das Problem mit denselben Projektdateien reproduzieren kann. Wenn dies möglich ist, senden Sie einen Fehlerbericht über Microsoft Connect.
Owen Wengerd
Ich entschuldige mich dafür, dass ich nicht angegeben habe, welches Projekt ich optimiert habe. Ich habe die Anweisung aktualisiert, um zu zeigen, dass ich die Ressourcendatei des niedrigsten ( B ) Projekts geändert habe. Ich werde das weiter untersuchen, da ich wahrscheinlich 1 Stunde am Tag verliere und auf unnötige Umbauten warte.
Matt Klein
0

Ich hatte die gleichen Probleme mit dir. Ich fand, dass es von einigen gelöschten Dateien kam. Als ich die Dateien aus meinem Projekt entfernt hatte, waren die Probleme verschwunden. Grüße.

PhonPanom
quelle
0

Für diese Kategorie von Build-Problemen ist es in der Tat ein notwendiger erster Schritt, die Ausführlichkeit der MSBuild-Ausgabe auf "Diagnose" zu setzen. In den meisten Fällen würde der angegebene Grund für die Neuerstellungen ausreichen, um darauf zu reagieren, ABER gelegentlich behauptete MSBuild fälschlicherweise, dass einige Dateien geändert wurden und kopiert werden müssen.

In diesem Fall müssen Sie entweder das NTFS-Tunneling deaktivieren oder Ihren Ausgabeordner an einen neuen Speicherort duplizieren. Hier ist es in mehr Worten.

Ofek Shilon
quelle
0

Ein weiteres Problem, das häufig auftritt, besteht darin, dass ein Element in Ihrer Lösung einen geänderten Stempel hat, der in der Zukunft liegt. Dies kann passieren, wenn Sie Ihre Uhr vorwärts stellen und dann Ihre Uhr auf die richtige Zeit einstellen. Ich hatte dies während der Installation von Linux passiert.

In diesem Fall können Sie alle Dateien mit git bash rekursiv berühren (ja, in Windows):

find . -exec touch {} \;
Mikhail
quelle
0

Ich hatte das Problem, dass Visual Studio beim Upgrade von Visual Studio 2015 auf 2017 Projekte neu erstellt, und füge diese Antwort zum Nutzen derjenigen hinzu, bei denen möglicherweise ähnliche Probleme auftreten, da sie anscheinend nirgendwo dokumentiert sind.

In meinem Fall bestand das Problem darin, dass alle Projekte in der Lösung denselben Zwischenausgabepfad (obj) hatten. Die Datei GeneratedInternalTypeHelper.cs wird von allen Projekten generiert, die XAML enthalten. Bis zu Visual Studio 2015 hat der Erstellungsprozess anscheinend nicht nach dem Dateidatum dieser Datei gesucht, und daher ist kein Problem damit aufgetreten. Mit VS2017 wird das Dateidatum dieser Datei überprüft. Da ein späteres Projekt im Erstellungsprozess es überschreibt (mit demselben Inhalt), wird das frühere Projekt neu erstellt und der spätere Build ad infinitum erneut ausgelöst.

In diesem Fall besteht die Lösung darin, sicherzustellen, dass alle Projekte unterschiedliche Zwischenausgabeverzeichnisse haben, wodurch das Problem behoben wird.

Blitz
quelle
0

In meinem Fall (gemischte C # -, C ++ / CLI- und native C ++ - Lösung) wurden einige C ++ - Projekte erneut verknüpft, auch wenn sich nichts geändert hatte. Ich habe ewig versucht herauszufinden, was passiert ist. Am Ende habe ich über die Option "Befehlszeile" herausgefunden, dass der PDB-Ausgabepfad (Option / Fd) die Ordnereinstellung $ (IntDir) nicht verarbeiten kann. Ich habe das entfernt - ein leerer Wert wird die Standardeinstellung korrekt ausführen - und mein Problem wurde behoben.

user11657883
quelle
0

Wie andere bemerkt haben, ist ein wahrscheinlicher Grund, dass CopyToOutputDirectory auf Always gesetzt ist. Dies kann gleichzeitig in allen Projektdateien behoben werden, indem das folgende Powershell-Skript angewendet wird:

$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
}
Jesper Mygind
quelle
0

Bei .Net-Kernprojekten funktionieren alle oben genannten Lösungen nicht. Ich habe die Lösung gefunden. Falls Sie Visual Studio 2019 verwenden:

  1. Erstellen Sie die Lösung zweimal
  2. Einschalten Tools-> Options-> Projects and Solutions-> SDK-Style Projects-> Logging Level->Verbose
  3. Löschen Sie das Ausgabefenster
  4. Erstellen Sie Ihr Startprojekt
  5. Überprüfen Sie das Ausgabefenster. Die ganze Zeichenfolge beginnt mitFastUpToDate
  6. Sie finden einige Projektelemente, die Ihr Projekt nicht auf den neuesten Stand bringen.
  7. Beheben Sie diese Probleme und versuchen Sie es ab Schritt 1 erneut. Wenn Ihre Korrekturen korrekt sind, erreichen Sie Build: 0 succeeded, 0 failed, {n} up-to-date, 0 skippeddie letzte Zeichenfolge der Build-Ausgabe.
Mikolaytis
quelle