it-swarm.com.de

MSBuild kopiert keine Verweise (DLL-Dateien), wenn Projektabhängigkeiten in der Projektmappe verwendet werden

Ich habe vier Projekte in meiner Visual Studio-Lösung (alle auf .NET 3.5 ausgerichtet) - für mein Problem sind nur diese beiden wichtig:

  1. MyBaseProject <- Diese Klassenbibliothek verweist auf eine DLL -Datei eines Drittanbieters (elmah.dll).
  2. MyWebProject1 <- Dieses Webanwendungsprojekt enthält einen Verweis auf MyBaseProject

Ich habe den elmah.dll-Verweis auf MyBaseProject in Visual Studio 2008 hinzugefügt, indem ich auf "Verweis hinzufügen ..." → Registerkarte "Durchsuchen" → Auswahl der "elmah.dll" geklickt habe.

Die Eigenschaften der Elmah-Referenz lauten wie folgt:

  • Aliase - global
  • Copy local - true
  • Kultur -
  • Beschreibung - Fehlerprotokollierungsmodule und -handler (ELMAH) für ASP.NET
  • Dateityp - Assembly
  • Pfad - D:\webs\otherfolder\_myPath\__ tools\elmah\Elmah.dll
  • Gelöst - wahr
  • Laufzeitversion - v2.0.50727
  • Angegebene Version - falsch
  • Starker Name - falsch
  • Version - 1.0.11211.0

In MyWebProject1 habe ich den Verweis auf Project MyBaseProject folgendermaßen hinzugefügt: "Verweis hinzufügen ..." → Registerkarte "Projects" → Auswahl von "MyBaseProject". Die Eigenschaften dieser Referenz sind mit Ausnahme der folgenden Elemente identisch:

  • Beschreibung -
  • Pfad - D:\webs\CMS\MyBaseProject\bin\Debug\MyBaseProject.dll
  • Version - 1.0.0.0

Wenn ich den Build in Visual Studio ausführe, wird die Datei elmah.dll zusammen mit MyBaseProject.dll in mein Bin von MyWebProject1 Verzeichnis kopiert!

Wenn ich jedoch MSBuild für die Lösung bereinige und ausführe (über D:\webs\CMS> C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe/t: ReBuild/p: Konfiguration = Debuggen Sie MyProject.sln) das elmah.dll fehlt im bin-Verzeichnis von MyWebProject1 - obwohl der Build selbst keine Warnung oder Fehler enthält!

Ich habe bereits sichergestellt, dass das .csproj von MyBaseProject das private -Element mit dem Wert "true" enthält (dies sollte ein Alias ​​für "copy local" in Visual Studio sein):

<Reference Include="Elmah, Version=1.0.11211.0, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\mypath\__tools\elmah\Elmah.dll</HintPath>
    **<Private>true</Private>**
</Reference>

(Das private Tag wurde standardmäßig nicht in der XML-Datei von .csproj angezeigt, obwohl Visual Studio "copy local" auf "true" gesetzt hat. Ich habe "copy local" auf "false" gesetzt - gespeichert - und wieder auf "true" gesetzt - speichern!)

Was ist los mit MSBuild? Wie bekomme ich die Referenz (elmah.dll) in den Bin von MyWebProject1 kopiert?

Ich möchte NICHT jedem Postbuild-Befehl eines Projekts eine Postbuild-Kopieraktion hinzufügen! (Stellen Sie sich vor, ich hätte viele Projekte, die von MyBaseProject abhängen!)

259
toebens

Ich bin nicht sicher, warum es beim Erstellen zwischen Visual Studio und MsBuild anders ist, aber Folgendes habe ich gefunden, wenn ich dieses Problem in MsBuild und Visual Studio angetroffen habe.

Erläuterung

Für ein Beispielszenario nehmen wir an, dass wir Projekt X, Assembly A und Assembly B haben. Assembly A verweist auf Assembly B, sodass Projekt X einen Verweis auf A und B enthält. Projekt X enthält auch Code, der auf Assembly A verweist (z. B. A). SomeFunction ()). Jetzt erstellen Sie ein neues Projekt Y, das auf Projekt X verweist.

Die Abhängigkeitskette sieht also so aus: Y => X => A => B

Visual Studio/MSBuild versucht, intelligent zu sein und Verweise nur in Projekt Y zu übernehmen, das von Projekt X als erforderlich erkannt wird. Dies geschieht, um eine Referenzverschmutzung in Projekt Y zu vermeiden. Das Problem ist, da Projekt X eigentlich keinen Code enthält, der explizit Assembly B verwendet (z. B. B.SomeFunction ()). VS/MSBuild erkennt nicht, dass B erforderlich ist von X und kopiert es daher nicht in das bin-Verzeichnis von Projekt Y; es kopiert nur die X- und A-Baugruppen.

Lösung

Sie haben zwei Möglichkeiten, dieses Problem zu lösen. Beides führt dazu, dass Assembly B in das bin-Verzeichnis von Projekt Y kopiert wird:

  1. Fügen Sie in Projekt Y einen Verweis auf Assembly B hinzu.
  2. Fügen Sie einer Datei in Projekt X Dummy-Code hinzu, der Assembly B verwendet.

Ich persönlich bevorzuge Option 2 aus ein paar Gründen.

  1. Wenn Sie in Zukunft ein anderes Projekt hinzufügen, das auf Projekt X verweist, müssen Sie nicht daran denken, auch einen Verweis auf Assembly B hinzuzufügen (wie Sie es bei Option 1 tun müssten).
  2. Sie können explizite Kommentare dazu erhalten, warum der Dummy-Code vorhanden sein muss und nicht entfernt werden soll. Wenn also jemand den Code versehentlich löscht (beispielsweise mit einem Refactor-Tool, das nach nicht verwendetem Code sucht), können Sie in der Quellcodeverwaltung leicht erkennen, dass der Code erforderlich ist, und ihn wiederherstellen. Wenn Sie Option 1 verwenden und jemand ein Refactor-Tool zum Bereinigen nicht verwendeter Referenzen verwendet, haben Sie keine Kommentare. Sie werden nur sehen, dass eine Referenz aus der .csproj-Datei entfernt wurde.

Hier ist ein Beispiel für den "Dummy-Code", den ich normalerweise hinzufüge, wenn ich auf diese Situation stoße.

    // DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE Assembly A!!!
    private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
    {
        // Assembly A is used by this file, and that Assembly depends on Assembly B,
        // but this project does not have any code that explicitly references Assembly B. Therefore, when another project references
        // this project, this project's Assembly and the Assembly A get copied to the project's bin directory, but not
        // Assembly B. So in order to get the required Assembly B copied over, we add some dummy code here (that never
        // gets called) that references Assembly B; this will flag VS/MSBuild to copy the required Assembly B over as well.
        var dummyType = typeof(B.SomeClass);
        Console.WriteLine(dummyType.FullName);
    }
141
deadlydog

Ich gehe einfach so damit um. Gehen Sie zu den Eigenschaften Ihrer Referenz und tun Sie dies:

Set "Copy local = false"
Save
Set "Copy local = true"
Save

und das ist es.

Visual Studio 2010 setzt zunächst nicht Folgendes: <private>True</private> im Referenztag und die Einstellung "copy local" auf false bewirkt, dass der Tag erstellt wird. Danach wird es entsprechend auf true und false gesetzt.

165
andrew

Wenn Sie die Assembly nicht direkt im Code verwenden, stellt Visual Studio fest, dass es nicht verwendet wird und nimmt es nicht in die Ausgabe auf. Ich bin nicht sicher, warum Sie ein unterschiedliches Verhalten zwischen Visual Studio und MSBuild feststellen. Sie könnten versuchen, die Build-Ausgabe für beide auf diagnostisch zu setzen und die Ergebnisse zu vergleichen, um zu sehen, wo sie auseinander gehen.

Wenn Sie die elmah.dll-Referenz nicht direkt im Code referenzieren, können Sie sie Ihrem Projekt als Element hinzufügen und die Build-Aktion auf Content und das In Ausgabeverzeichnis kopieren auf Always setzen.

38
John Hunter

Schauen Sie sich an:

Diesen MSBuild Forumsthread habe ich gestartet

Dort finden Sie meine temporäre Lösung/Workaround!

(MyBaseProject benötigt etwas Code, der auf einige Klassen der elmah.dll verweist, da elmah.dll in die Bin von MyWebProject1 kopiert wird!)

14
toebens

Ich hatte das gleiche Problem.

Überprüfen Sie, ob die Framework-Version Ihres Projekts mit der Framework-Version der DLL übereinstimmt, auf die Sie verweisen.

In meinem Fall wurde mein Client mit "Framework 4 Client" kompiliert und die DLL befand sich in "Framework 4".

8
Andre Avelar

Mein Problem war, dass ich ein Projekt habe, das von einem Bibliotheksprojekt abhängig ist. Um zu bauen, folgte ich diesen Schritten:

msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package

Das bedeutete natürlich, dass mir die DLL-Dateien meiner Bibliothek in bin und vor allem in der ZIP-Datei des Pakets fehlten. Ich fand das funktioniert perfekt:

msbuild.exe myproject.vbproj /T:Rebuild;Package

Ich habe keine Ahnung, warum diese Arbeit oder warum es überhaupt nicht funktioniert hat. Aber hoffe das hilft.

6
vangorra

Wie Alex Burtsev in einem Kommentar alles erwähnte, was nur in einem XAML-Ressourcenwörterbuch oder in meinem Fall verwendet wird, wird alles, was nur in XAML und nicht im Code dahinter verwendet wird, von MSBuild nicht als "in Gebrauch" angesehen. 

Es war also genug, MSBuild davon zu überzeugen, dass die Assembly tatsächlich verwendet wurde.

4
Scott

Ich hatte gerade das gleiche Problem und es stellte sich heraus, dass zwei Projekte in derselben Lösung auf eine andere Version der Drittanbieter-Bibliothek verweisen. 

Nachdem ich alle Referenzen korrigiert hatte, funktionierte alles perfekt.

3
Steven Engels

Mit dem Deadlydog-Schema 

Y => X => A => B

mein Problem war, als ich Y baute, die Baugruppen (A und B, alle 15) von X wurden nicht in Ys Ordner "Bin" angezeigt.

Ich löste es, indem ich den Verweis X von Y entfernte, speichern, erstellen und dann X-Verweis (eine Projektreferenz) wieder hinzufügen und speichern, erstellen und A und B im y-Ordner bin.

3
J Z

Das Ändern des Zielframeworks von .NET Framework 4-Clientprofil in .NET Framework 4 hat dieses Problem für mich behoben.

Also in Ihrem Beispiel: Setzen Sie das Zielframework in MyWebProject1 auf .NET Framework 4

3
Fuyu Persimmon

Dazu müssen Sie Ihrem Projekt eine .targets-Datei hinzufügen und diese in den Include-Abschnitt des Projekts aufnehmen.

Siehe meine Antwort hier für das Verfahren.

2
Alex Essilfie

Das Referenzieren von Baugruppen, die während des Builds nicht verwendet werden, ist nicht die richtige Vorgehensweise. Sie sollten Ihre Build-Datei so erweitern, dass die zusätzlichen Dateien kopiert werden. Entweder mithilfe eines Post Build-Ereignisses oder durch Aktualisieren der Eigenschaftsgruppe. 

Einige Beispiele finden Sie in einem anderen Beitrag

2
verbedr

Ich hatte das gleiche Problem und die DLL war eine dynamisch geladene Referenz. Um das Problem zu lösen, habe ich ein "using" mit dem Namespace der DLL hinzugefügt.

2
Spamme

Ein anderes Szenario, in dem dies angezeigt wird, ist, wenn Sie den älteren Projekttyp "Website" in Visual Studio verwenden. Bei diesem Projekttyp kann auf DLLs nicht verwiesen werden, die sich außerhalb der eigenen Verzeichnisstruktur befinden (aktueller Ordner und heruntergefahren). Nehmen wir an, dass Ihre Verzeichnisstruktur in der obigen Antwort so aussieht:

 enter image description here

Wo ProjectX und ProjectY übergeordnete/untergeordnete Verzeichnisse sind und ProjectX auf A.dll verweist, die wiederum auf B.dll verweist, und B.dll außerhalb der Verzeichnisstruktur liegt, z. dll wird enthalten sein, aber B.dll nicht. 

2
Focker

Stellen Sie sicher, dass sich beide Projekte in derselben .net-Version befinden. Überprüfen Sie auch die lokale Kopiereigenschaft. Dies sollte jedoch true sein

0
john.kernel

Ich hatte heute ein ähnliches Problem, und dies ist sicherlich nicht die Antwort auf Ihre Frage. Aber ich möchte alle informieren und möglicherweise einen Funken Einblick gewähren.

Ich habe eine ASP.NET-Anwendung. Der Erstellungsprozess ist auf Bereinigen und dann Erstellen eingestellt.

Ich habe zwei JenkinsCI Skripte. Einer für die Produktion und einer für die Inszenierung. Ich stellte meine Anwendung für das Staging bereit und alles hat gut funktioniert. Für die Produktion bereitgestellt und es fehlte eine DLL -Datei, auf die verwiesen wurde. Diese Datei DLL befand sich nur im Stammverzeichnis des Projekts. Nicht in einem NuGet-Repository. Die DLL wurde auf do not copy gesetzt.

Das CI-Skript und die Anwendung waren in beiden Bereitstellungen identisch. Nach dem Bereinigen und Bereitstellen in der Staging-Umgebung wurde die Datei DLL am Bereitstellungsspeicherort der ASP.NET-Anwendung (bin/) ersetzt. Dies war in der Produktionsumgebung nicht der Fall.

In einem Testzweig stellte sich heraus, dass ich dem Build-Prozess einen Schritt hinzugefügt hatte, um diese DLL -Datei in das Verzeichnis bin zu kopieren. Nun, der Teil, der etwas Zeit brauchte, um herauszufinden. Der CI-Prozess hat sich nicht selbst gereinigt. Die DLL wurde im Arbeitsverzeichnis belassen und wurde versehentlich mit der ASP.NET-ZIP-Datei gepackt. Der Produktionszweig hat die DLL -Datei niemals auf dieselbe Weise kopiert und diese nie aus Versehen bereitgestellt.

TLDR; Überprüfen Sie, ob Sie wissen, was Ihr Build-Server tut.

0
Jason Portnoy

Ich bin gerade auf eine sehr ähnliche Ausgabe gestoßen. Beim Kompilieren mit Visual Studio 2010 wurde die Datei DLL im Ordner bin enthalten. Beim Kompilieren mit MSBuild wurde die Drittanbieter-Datei DLL nicht enthalten.

Sehr frustrierend. Wie ich es gelöst habe, bestand darin, den NuGet - Verweis auf das Paket in mein Webprojekt aufzunehmen, obwohl ich es nicht direkt dort verwende.

0
Gary Brunton