Die abhängige DLL wird in Visual Studio nicht in den Build-Ausgabeordner kopiert

185

Ich habe eine visuelle Studiolösung. Ich habe viele Projekte in der Lösung. Es gibt ein Hauptprojekt, das als Start fungiert und andere Projekte verwendet. Es gibt ein Projekt namens "ProjectX". Die Referenz wird dem Hauptprojekt hinzugefügt. ProjectX verweist auf eine andere .NET-DLL (z. B. abc.dll), die nicht Teil der Lösung ist.

Jetzt sollte diese abc.dll in den Ordner bin / debug des Hauptprojekts kopiert werden, wird dort aber nicht kopiert. Warum wird es aus bekannten Gründen nicht kopiert?

Brij
quelle
Wenn Sie dies nicht herausfinden können, kopieren Sie es in Ihren Prebuild.
Dilshod
Wie verwenden Sie Ihr 'ProjectX' im Hauptprojekt - welche Art von Projekt, Ziel usw.
NSGaga - meistens inaktiv
Ich hatte das gleiche Problem und diese Antwort löste mein Problem: stackoverflow.com/a/8213977/174469
Gordon Tucker
Es ist eine RestoreProjectStyle Lösung verfügbar . Die Idee ist, <RestoreProjectStyle>PackageReference</RestoreProjectStyle>für jedes .NET Framework-Projekt in der Lösung festzulegen.
Oleksa

Antworten:

105

Ich fand heraus, dass abc.dll NICHT in den Hauptausgabeordner kopiert wird, wenn ProjectX auf die abc.dll verweist, aber keinen der in abc.dll DEFINIERTEN Typen direkt verwendet. (Es wird in den ProjectX-Ausgabeordner kopiert, um es besonders verwirrend zu machen.)

Wenn Sie also an keiner Stelle in ProjectX explizit einen der Typen aus abc.dll verwenden, fügen Sie irgendwo in einer der Dateien in ProjectX eine Dummy-Deklaration ein.

AbcDll.AnyClass dummy006; // this will be enough to cause the DLL to be copied

Sie müssen dies nicht für jede Klasse tun - nur ein einziges Mal reicht aus, damit die DLL-Kopie erstellt wird und alles wie erwartet funktioniert.

Nachtrag: Beachten Sie, dass dies möglicherweise für den Debug-Modus funktioniert, jedoch NICHT für die Veröffentlichung. Weitere Informationen finden Sie in der Antwort von @ nvirth.

Oberherr Zurg
quelle
7
Das scheint ein Hack zu sein. Das Hinzufügen des Verweises zum Hauptprojekt scheint ausreichend zu sein.
Mike K
3
Es ist ein Hack, aber wie uns die heutigen CodeProject-Nachrichten gelehrt haben, können sogar Compiler falsch liegen!
Overlord Zurg
4
Wie verrückt Dinge sein können. @OverlordZurg Ihre Lösung funktionierte, da ich einen Verweis auf die abhängige DLL in meiner XAML (WPF) hatte und die DLL nicht in das Hauptprojekt kopierte, bis ich eine einfache Dummy-Referenz hinzufügte, wie Sie sagten ... Trotzdem danke
Mohsen Afshin
5
@MohsenAfshin Ich hatte das gleiche Problem --- Ich habe auf eine abhängige DLL in XAML verwiesen. Anstatt eine Dummy-Variable zu deklarieren, habe ich einfach die Komponente benannt, die ich in XAML verwendet habe, und das hat ausgereicht, um die Assembly zu kopieren.
Redcurry
5
@MikeK Das Hinzufügen zum Hauptprojekt (das eigentlich nicht direkt davon abhängt) ist ein noch größerer Hack, imo. Dann müssen Sie es an zwei Stellen verwalten ("verwalten" wie beim Upgrade oder Entfernen). Bei diesem Hack wird zumindest ein Fehler beim Kompilieren angezeigt, der Sie daran erinnert, diesen Hack zu entfernen, wenn Sie die Abhängigkeit entfernen, und Sie müssen ihn immer noch nur an einer Stelle aktualisieren.
jpmc26
70

Nur eine Nebenbemerkung zu Overlord Zurgs Antwort.

Ich habe die Dummy-Referenz auf diese Weise hinzugefügt und sie hat im Debug-Modus funktioniert:

public class DummyClass
{
    private static void Dummy()
    {
        var dummy = typeof(AbcDll.AnyClass);
    }
}

Im Release-Modus wurde die abhängige DLL jedoch immer noch nicht kopiert.
Dies funktionierte jedoch:

public class DummyClass
{
    private static void Dummy()
    {
        Action<Type> noop = _ => {};
        var dummy = typeof(AbcDll.AnyClass);
        noop(dummy);
    }
}

Diese Informationen haben mich tatsächlich Stunden gekostet, um herauszufinden, also dachte ich, ich teile sie.

nvirth
quelle
6
Im Release-Modus geht das Optimierungsprogramm davon aus, dass "Dummy" nicht verwendet wird, sodass diese Zeile nicht erforderlich ist und entfernt werden sollte. Wenn Sie jedoch "Dummy" im Code verwenden, geht das Optimierungsprogramm nicht davon aus, dass dies nicht erforderlich ist.
Yucel
1
Dies funktioniert nicht für mich.AbcDll.AnyClass wird immer noch nicht in ein anderes Projekt kopiert
Matthew Lock
3
Stellen Sie sicher, dass AbcDll.AnyClasses als öffentliches Feld oder Eigenschaft in einer öffentlichen Klasse verwendet wird, dann funktioniert es. Wenn Sie es in einem Verfahren Körper wie dies der Compiler verwendet nicht sehen es . Das Laden dieser Assembly wird verzögert, nicht das, was Sie möchten.
John Leidegren
52

Ja, Sie setzen müssen , Copy Localum true. Allerdings bin ich ziemlich sicher , dass Sie auch Referenz benötigen , die Baugruppe aus dem Hauptprojekt und Satz Copy Localauf trueund - es ist nicht nur aus einer abhängigen Assembly kopiert werden.

Sie gelangen zur Copy LocalEigenschaft, indem Sie auf die Baugruppe unter klicken Referencesund F4 drücken.

Mike Perrenoud
quelle
2
@Brij, wird die Assembly aus dem Hauptprojekt referenziert, in dem Sie sie haben möchten? Wie gesagt, ich bin mir ziemlich sicher, dass Sie auch auf dieses Projekt verweisen müssen - abhängige Assemblys werden nicht so kopiert. In diesem Fall müssten Sie die Baugruppen bei Verwendung von NuGet nicht allen relevanten Projekten hinzufügen.
Mike Perrenoud
1
Was war die Schlussfolgerung hier? Es scheint mir, dass Sie Recht haben - abhängige Referenzen werden nicht kopiert, selbst wenn CopyLocal auf true gesetzt ist - welche Logik steckt dahinter?
Mcmillab
29
@mcmillab, kurz gesagt Visual Studio nicht schließen Abhängigkeiten von anderen abhängigen Projekten. Wenn Projekt A auf Projekt B verweist, muss Projekt A alle Referenzen von Projekt B enthalten. Es funktioniert gut, wenn Projekt B nur .NET-Assemblys benötigt. Wenn es sich jedoch um eine Assembly eines Drittanbieters handelt, müssen Sie den Verweis auf beide Projekte hinzufügen.
Mike Perrenoud
12
@ MichaelPerrenoud Ich glaube nicht, dass das stimmt. Wenn Sie sich eine detaillierte MSBuild-Ausgabe ansehen, werden Aufrufe von ResolveAssemblyReference angezeigt, in denen angegeben ist, dass "Abhängigkeiten zweiter und n-ter Ordnung enthalten sind". Dies stimmt auch mit dem überein, was ich in meinen Bin-Ordnern sehe (n-te Abhängigkeiten werden kopiert). Das Problem ist, dass es einige Einschränkungen gibt, was kopiert wird, hauptsächlich in Bezug auf GAC und indirekte Verweise (Verweis
hinzufügen
2
Meine aktuelle Erfahrung ist, dass dies mit Ausnahme von 'kopierten' Abhängigkeiten funktioniert: Projekt A.net verweist auf externe C ++ - DLLs als Dateien, die 'immer kopieren' sind. Projekt B.net verweist auf Projekt A. Beim Erstellen enthält B / Debug die C ++ - DLLs. Wenn ich jedoch Anwendung X erstelle, die auf Projekt B verweist, werden die C ++ - DLLs manchmal kopiert (scheint nur zu sein, wenn ich eine Neuerstellung durchführe).
Benjol
33

Es sieht gut aus, wenn Sie es zu einem Assembly-Attribut machen

[AttributeUsage(AttributeTargets.Assembly)]
public class ForceAssemblyReference: Attribute
{        
    public ForceAssemblyReference(Type forcedType)
    {
        //not sure if these two lines are required since 
        //the type is passed to constructor as parameter, 
        //thus effectively being used
        Action<Type> noop = _ => { };
        noop(forcedType);
    }
}

Die Verwendung wird sein:

[assembly: ForceAssemblyReference(typeof(AbcDll.AnyClass))]
Aryéh Radlé
quelle
Vielen Dank, aber für mich bedeutet dies nur, wenn ich das Assembly-Attribut zur Abhängigkeit (Project X) hinzufüge, die bereits auf die AbcDll.AnyClass verweist. Und dann macht es nicht mehr als normal, wo es die AbcDll in das Ausgabeverzeichnis der Abhängigkeit kopiert. Es wird immer noch nicht in die Ausgabe des abhängigen Hauptprojekts kopiert. Und ich kann das Attribut nicht der abhängigen Assembly hinzufügen, es sei denn, ich füge auch einen Verweis auf AbcDll hinzu. Wenn ich das mache, wird AbcDll bereits ohne das Attribut kopiert.
JS
25

Bin auf dasselbe Problem gestoßen. Hintergrundinfo: Vor dem Erstellen hatte ich der Lösung ein neues Projekt X hinzugefügt. Projekt Y hing von Projekt X ab und Projekt A, B, C hingen von Projekt Y ab.

Build-Fehler waren, dass Projekt-A-, B-, C-, Y- und X-DLLs nicht gefunden werden konnten.

Die Hauptursache war, dass das neu erstellte Projekt X auf .NET 4.5 abzielte, während der Rest der Lösungsprojekte auf .NET 4.5.1 abzielte. Projekt X wurde nicht erstellt, sodass auch der Rest der Projekte nicht erstellt wurde.

Stellen Sie sicher, dass alle neu hinzugefügten Projekte auf dieselbe .NET-Version abzielen wie der Rest der Lösung.

Darren Alfonso
quelle
1
Referenzierte Projekte sind möglicherweise eine ältere Version von .NET. Ich kann auf ein Projekt verweisen, das für .NET 4 von einem für .NET 4.5 erstellten Projekt erstellt wurde.
Redcurry
18

Ich bin mir nicht sicher, ob dies hilft, aber für mich verweise ich oft auf eine DLL (die sie natürlich automatisch zum Ordner bin hinzufügt). Diese DLL benötigt jedoch möglicherweise zusätzliche DLLs (abhängig davon, welche Funktionen ich verwende). Ich möchte NICHT auf diese in meinem Projekt verweisen, da sie nur im selben Ordner wie die DLL landen müssen, die ich tatsächlich verwende.

Ich erreiche dies in Visual Studio durch "Hinzufügen einer vorhandenen Datei". Sie sollten es an einer beliebigen Stelle außer im Ordner Add_data hinzufügen können. persönlich füge ich es einfach der Wurzel hinzu.

Ändern Sie dann die Eigenschaften dieser Datei in ...

Build Action = None (wenn dies auf so etwas wie Content gesetzt ist, wird die "root" -Version in den root kopiert, plus eine Kopie im Bin).

In Ausgabeordner kopieren = Bei Neuem kopieren (Im Grunde genommen wird es nur dann in den BIN-Ordner gelegt, wenn es fehlt, danach aber nicht mehr)

Wenn ich veröffentliche, sind meine hinzugefügten DLLs nur im BIN-Ordner und nirgendwo anders im Veröffentlichungsspeicherort vorhanden (was ich möchte).

da_jokker
quelle
10

Sie können auch überprüfen, ob die gesuchten DLLs nicht im GAC enthalten sind. Ich glaube, Visual Studio ist schlau, diese Dateien nicht zu kopieren, wenn sie bereits im GAC auf dem Buildcomputer vorhanden sind.

Ich bin kürzlich in dieser Situation gelaufen, in der ich ein SSIS-Paket getestet hatte, für das Assemblys im GAC erforderlich waren. Ich hatte das seitdem vergessen und mich gefragt, warum diese DLLs während eines Builds nicht herauskamen.

So überprüfen Sie, was sich im GAC befindet (über eine Eingabeaufforderung für Visual Studio Developer):

gacutil -l

Oder in eine Datei ausgeben, um das Lesen zu erleichtern:

gacutil -l > output.txt
notepad.exe output.txt

So entfernen Sie eine Baugruppe:

gacutil -u MyProjectAssemblyName

Ich sollte auch beachten, dass die Dateien, nachdem ich sie aus dem GAC entfernt hatte, nach einem Build korrekt im Verzeichnis \ bin ausgegeben wurden (auch für Assemblys, auf die im Root-Projekt nicht direkt verwiesen wurde). Dies war in Visual Studio 2013 Update 5.

Brett
quelle
Vielen Dank, Sie haben Recht, MSBuild kopiert die DLL nicht in den Ausgabeordner, wenn es sie im GAC gefunden hat.
John-Philip
3

In meinem Fall war es das Dümmste, verursacht durch ein Standardverhalten von TFS / VS, mit dem ich nicht einverstanden bin.

Da das Hinzufügen der DLL als Referenz zum Hauptprojekt nicht funktioniert hat, habe ich beschlossen, sie als "Vorhandenes Element" mit "Lokal kopieren = Immer" hinzuzufügen. Selbst dann war die Datei nicht da.

Es stellt sich heraus, dass VS / TFS die Datei nicht zur Quellcodeverwaltung hinzugefügt hat, obwohl die Datei in der VS-Lösung vorhanden ist und alles lokal und auf dem Server kompiliert wurde. Es war überhaupt nicht in den "Ausstehenden Änderungen" enthalten. Ich musste manuell zum Versionsverwaltungs-Explorer gehen und explizit auf das Symbol "Elemente zum Ordner hinzufügen" klicken.

Dumm, weil ich mich seit 15 Jahren in VS entwickle. Ich bin schon einmal darauf gestoßen, ich habe mich einfach nicht daran erinnert und irgendwie habe ich es verpasst, weil alles noch kompiliert wurde, weil die Datei eine reguläre Referenz ist, aber die Datei, die als vorhandenes Element hinzugefügt wurde, wurde nicht kopiert, weil sie nicht vorhanden war der Quellcodeverwaltungsserver.

Ich hoffe, das spart jemandem etwas Zeit, da ich 2 Tage meines Lebens dadurch verloren habe.

GR7
quelle
1
Ich kann dir nicht genug danken ... du hast mir so viel Zeit gespart. Das war eine Lösung für mich. Außerdem wurde das Root-Problem aufgedeckt. Die DLL, die ich als Referenz hinzugefügt habe, stimmte mit einem gitignoreMuster überein. Beim Hinzufügen als Referenz wurde sie dem Projekt nicht hinzugefügt. Sie MÜSSEN die Datei manuell zur Quellcodeverwaltung hinzufügen !!!
Mattkwish
2

Dies ist eine kleine Änderung am Beispiel von nvirth

internal class DummyClass
{
    private static void Dummy()
    {
        Noop(typeof(AbcDll.AnyClass));
    }
    private static void Noop(Type _) { }
}
maca134
quelle
2

Ich würde es zu Postbuild-Ereignissen hinzufügen, um die erforderlichen Bibliotheken in die Ausgabeverzeichnisse zu kopieren. So etwas wie das Zielverzeichnis der XCopy-Pathtolibraries

Sie finden sie unter Projekteigenschaften -> Ereignisse erstellen.

Chethan Jain
quelle
Das hat bei mir funktioniert und ich denke, das ist die bessere Antwort. Die Dummy-Referenzlösung funktioniert, ist aber ein Hack, während eine Post-Build-Regel ein sauberer Weg ist, um das gleiche Ergebnis zu erzielen.
Kevin Fichter
2

Problem:

Es ist ein ähnliches Problem bei einer NuGet-Paket-DLL (Newtonsoft.json.dll) aufgetreten, bei der die Build-Ausgabe die referenzierte DLL nicht enthält. Aber die Zusammenstellung geht gut durch.

Fix:

Gehen Sie Ihre Projekte in einem Texteditor durch und suchen Sie nach Referenzen mit Tags. Wie wahr oder falsch. "Privat" ist ein Synonym für "Lokal kopieren". Irgendwo in den Aktionen sucht MSBuild nach Abhängigkeiten, findet Ihre Abhängigkeit woanders und beschließt, sie nicht zu kopieren.

Gehen Sie also jede .csproj / .vbproj-Datei durch und entfernen Sie die Tags manuell. Neu erstellen, und alles funktioniert sowohl in Visual Studio als auch in MSBuild. Sobald das funktioniert hat, können Sie zurückgehen und das aktualisieren, wo Sie denken, dass es sein muss.

Referenz:

https://www.paraesthesia.com/archive/2008/02/13/what-to-do-if-copy-local-works-in-vs-but.aspx/

Nkl Kumar
quelle
1

KEINE NOTWENDIGKEIT FÜR DUMMY IM CODE
Nur:

Fügen Sie einen Verweis auf das ausführbare Projekt hinzu

oder / und stellen Sie sicher, dass die Referenz im ausführbaren Projekt "Copy Local"auf TRUE(was mein " Fehler " war) gesetzt wurde, dass dies die Einstellung im Basis-referenzierten Bibliotheksprojekt "überschrieben" hat ...

Cadburry
quelle
1

Wenn Sie mit der rechten Maustaste auf die Assembly klicken, auf die verwiesen wird, wird eine Eigenschaft mit dem Namen " Lokal kopieren" angezeigt . Wenn Copy Local auf true gesetzt ist, sollte die Assembly in den Bin aufgenommen werden. Es gibt jedoch Probleme mit Visual Studio, dass die referenzierte DLL manchmal nicht im bin-Ordner enthalten ist. Dies ist die Problemumgehung, die für mich funktioniert hat:

Geben Sie hier die Bildbeschreibung ein

Hooman Bahreini
quelle
1
Copy Loal wurde deaktiviert, dies half stackoverflow.com/questions/15526491/…
codemirror
1

TLDR; Visual Studio 2019 muss möglicherweise einfach neu gestartet werden.

Ich bin auf diese Situation bei Projekten gestoßen, die auf dem Microsoft.NET.Sdk-Projekt basieren.

<Project Sdk="Microsoft.NET.Sdk">

Speziell:

  • Project1: Ziele .netstandard2.1
    • Referenzen Microsoft.Extensions.Logging.Consoleüber Nuget
  • Project2: Ziele .netstandard2.1
    • Referenzen Project1über eine Projektreferenz
  • Project2Tests: Ziele .netcoreapp3.1
    • Referenzen Project2über eine Projektreferenz

Bei der Testausführung erhielt ich die Fehlermeldung, dass diese Microsoft.Extensions.Logging.Consolenicht gefunden werden konnte und sich tatsächlich nicht im Ausgabeverzeichnis befand.

Ich habe mich entschlossen, das Problem durch Hinzufügen Microsoft.Extensions.Logging.Consolezu Project2zu umgehen, nur um festzustellen, dass der Nuget Manager von Visual Studio nicht Microsoft.Extensions.Logging.Consoleals installiert installiert wurdeProject1 trotz seiner Anwesenheit in der Project1.csprojDatei wurde .

Durch einfaches Herunterfahren und Neustarten von Visual Studio wurde das Problem behoben, ohne dass eine zusätzliche Referenz hinzugefügt werden musste. Vielleicht spart dies jemandem 45 Minuten Produktivitätsverlust :-)

Eric Patrick
quelle
Eigentlich habe ich den gesamten PC neu gestartet, um Dinge zu testen, aber es hat bei mir
funktioniert
0

Sie können sowohl das Hauptprojekt als auch den Build-Ausgabepfad von ProjectX auf denselben Ordner festlegen und dann alle benötigten DLLs in diesem Ordner abrufen.

YantingChen
quelle
0

Stellen Sie sicher, dass für die von Ihnen verwendete abhängige DLL kein höheres .net-Framework als das .net-Zielframework der Anwendung Ihres Projekts vorhanden ist.

Sie können dies überprüfen, indem Sie Ihr Projekt auswählen, dann ALT + EINGABETASTE drücken, dann auf der linken Seite Anwendung auswählen und dann Ziel-Framework Ihres Projekts auswählen.

Angenommen, das abhängige DLL-Zielframework = 4.0 und das Anwendungs-DLL-Zielframework = 3.5 ändern dies in 4.0

Danke dir!

Manish Jain
quelle
0

Abgesehen von den oben genannten hatte ich eine Lösung für mehrere Projekte zu veröffentlichen. Anscheinend zielen einige Dateien auf unterschiedliche Frameworks ab.

Also meine Lösung: Eigenschaften> Spezifische Version (Falsch)

RicL
quelle
0

Fügen Sie die DLL als vorhandenes Element zu einem der Projekte hinzu, und sie sollte sortiert werden

abhijithkarkal
quelle