webentwicklung-frage-antwort-db.com.de

Einrichten eines gemeinsamen Nuget-Paketordners für alle Lösungen, wenn einige Projekte in mehreren Lösungen enthalten sind

Ich habe NuGet verwendet, um Pakete aus externen und internen Paketquellen abzurufen, was sehr bequem ist. Ich habe jedoch festgestellt, dass die Pakete standardmäßig pro Lösung gespeichert werden, was sehr frustrierend ist, wenn einige Projekte mit NuGet-Referenzen in mehreren Lösungen enthalten sind. Die Verweise werden dann in einen anderen Lösungspaketordner geändert, der für einen anderen Entwickler oder Build-Computer möglicherweise nicht verfügbar ist.

Ich habe gesehen, dass es Möglichkeiten gibt, mit dem Release 2.1 von NuGet auf einen gemeinsamen Paketspeicherort hinzuweisen (vielleicht auf Projekt-Root-Ebene verwenden wir TFS-Quellcodeverwaltung), siehe Versionshinweise . Ich verwende NuGet v2.7

Ich habe jedoch versucht, nuget.config -Dateien hinzuzufügen, ohne dass dies Auswirkungen darauf hat. Pakete werden immer noch im Lösungsordner gespeichert. Gibt es etwas, das ich vermisst habe? Es scheint verschiedene Strukturen des xml-Knotens zu geben, die der Datei nuget.config hinzugefügt werden können, je nachdem, wer diese Frage beantwortet: Schwarzie schlägt Folgendes vor: Ein weiterer Stackoverflow-Thread :

<settings>
  <repositoryPath>..\..\[relative or absolute path]</repositoryPath>
</settings>

In den Versionshinweisen für NuGet 2.1 (siehe Link oben) wird dieses Format vorgeschlagen: 

<configuration>
  <config>
    <add key="repositoryPath" value="..\..\[relative or absolute path]" />
  </config>
</configuration>

Ich weiß nicht, welche davon oder welche oder beide am Ende funktionieren werden. Ich habe beides auf Lösungsebene ausprobiert. Kann die Datei nuget.config in der TFS-Projektebene platziert werden oder muss sie sich im Lösungsverzeichnis befinden? Es scheint, dass NuGet die Einstellungen aus diesen Dateien in einer bestimmten Reihenfolge liest und anwendet, weshalb es sinnvoll wäre, sie auf mehreren Ebenen hinzuzufügen, wobei eine Datei nuget.config auf Lösungsebene eine Ebene auf der Stammebene des TFS-Projekts überschreiben würde. Kann das geklärt werden?

Muss ich alle installierten Pakete entfernen, bevor diese Verweise funktionieren? Ich würde es sehr schätzen, wenn jemand eine schrittweise Anleitung zum Wechseln von der lösungsspezifischen Nuget-Nutzung in einen allgemeinen Paketordner mit Projekten bereitstellt, in denen mehrere Projekte vorhanden sind Lösungen finden ihre benötigten Nuget-Pakete.

121
Mats Isaksson

Ich habe eine ähnliche Situation mit externen und internen Paketquellen mit Projekten, auf die in mehr als einer Lösung verwiesen wird. Ich habe das gerade mit einer unserer Code-Basen gemacht und es scheint mit den Entwickler-Workstations und unserem Build-Server zu funktionieren. Der folgende Prozess berücksichtigt dieses Szenario (obwohl es nicht schwierig sein sollte, ihn anzupassen, um den gemeinsamen Paketordner an anderer Stelle zu haben).

  • Codebasis
    • Projekt A
    • Projekt B
    • Projekt C
    • Lösungen
      • Lösung 1
      • Lösung 2
      • Lösung 3
      • Pakete (dies ist das gemeinsame Paket aller Lösungen)

Aktualisierte Antwort ab NuGet 3.5.0.1484 mit Visual Studio 2015 Update 3

Dieser Prozess ist jetzt ein bisschen einfacher als zu dem Zeitpunkt, als ich dies ursprünglich in Angriff genommen hatte und dachte, es sei an der Zeit, dies zu aktualisieren. Im Allgemeinen ist der Prozess der gleiche, nur mit weniger Schritten. Das Ergebnis ist ein Prozess, der Folgendes löst oder bereitstellt:

  • Alles, was für die Quellcodeverwaltung erforderlich ist, wird in der Lösung angezeigt und nachverfolgt
  • Das Installieren neuer Pakete oder das Aktualisieren von Paketen mit dem Paket-Manager in Visual Studio verwendet den richtigen Repository-Pfad
  • Nach der Erstkonfiguration kein Hacken von .csproj-Dateien
  • Keine Änderungen an der Entwickler-Workstation (Code wird beim Auschecken fertig erstellt)

Es gibt einige mögliche Nachteile zu beachten (ich habe sie noch nicht erlebt, YMMV). Siehe Benols Antwort und Kommentare unten.

Fügen Sie NuGet.Config hinzu

Sie möchten eine NuGet.Config-Datei im Stammverzeichnis des Ordners\Solutions\erstellen. Stellen Sie sicher, dass es sich um eine UTF-8-codierte Datei handelt, die Sie erstellen. Wenn Sie nicht sicher sind, wie Sie dies tun sollen, verwenden Sie das Menü Datei-> Neu-> Datei von Visual Studio, und wählen Sie dann die XML-Dateivorlage aus. Fügen Sie zu NuGet.Config Folgendes hinzu:

<?xml version="1.0" encoding="utf-8"?>
<configuration>  
  <config>
    <add key="repositoryPath" value="$\..\Packages" />
  </config>
</configuration>

Für die Einstellung repositoryPath können Sie mit dem Token $ einen absoluten oder relativen Pfad (empfohlen) angeben. Das $ -Token basiert auf der Position von NuGet.Config (das $ -Token ist tatsächlich relativ zu einer Ebene unter der Position von NuGet.Config). Wenn ich also\Solutions\NuGet.Config habe und\Solutions\Packages möchte, muss ich $\..\Packages als Wert angeben.

Als Nächstes möchten Sie Ihrer Lösung einen Lösungsordner mit dem Namen "NuGet" hinzufügen (Klicken Sie mit der rechten Maustaste auf Ihre Lösung, Hinzufügen-> Neuer Lösungsordner). Lösungsordner sind virtuelle Ordner, die nur in der Visual Studio-Lösung vorhanden sind und keinen tatsächlichen Ordner auf dem Laufwerk erstellen (und Sie können von überall auf Dateien verweisen). Klicken Sie mit der rechten Maustaste auf Ihren "NuGet" -Lösungsordner und dann auf Hinzufügen-> Vorhandenes Element und wählen Sie\Solutions\NuGet.Config.

Der Grund, warum wir dies tun, ist, dass es in der Lösung sichtbar ist und dabei helfen soll, sicherzustellen, dass es Ihrer Quellcodeverwaltung ordnungsgemäß zugewiesen wird. Möglicherweise möchten Sie diesen Schritt für jede Lösung in Ihrer Codebasis ausführen, die an Ihren freigegebenen Projekten beteiligt ist.

Durch Platzieren der NuGet.Config-Datei in\Solutions\über allen .sln-Dateien nutzen wir die Tatsache, dass NuGet die Ordnerstruktur rekursiv vom "aktuellen Arbeitsverzeichnis" nach oben navigiert und nach einer NuGet.Config-Datei sucht, die verwendet werden kann. Das "aktuelle Arbeitsverzeichnis" bedeutet hier ein paar verschiedene Dinge, eines ist der Ausführungspfad von NuGet.exe und das andere ist der Speicherort der .sln-Datei.

Umschalten Ihres Paketordners

Als Erstes empfehle ich Ihnen dringend, jeden Ihrer Lösungsordner zu durchsuchen und alle vorhandenen\Packages\-Ordner zu löschen (Sie müssen Visual Studio zuerst schließen). Dies macht es einfacher zu sehen, wo NuGet Ihren neu konfigurierten\Packages\-Ordner ablegt und stellt sicher, dass Verknüpfungen zu falschen\Packages\-Ordnern fehlschlagen und dann repariert werden können.

Öffnen Sie Ihre Lösung in Visual Studio und starten Sie einen Neustart. Ignorieren Sie alle Build-Fehler, die Sie erhalten. Dies wird an dieser Stelle erwartet. Dies sollte jedoch die NuGet-Paketwiederherstellungsfunktion zu Beginn des Erstellungsprozesses auslösen. Stellen Sie sicher, dass Ihr\Solutions\Packages\-Ordner an der gewünschten Stelle erstellt wurde. Ist dies nicht der Fall, überprüfen Sie Ihre Konfiguration.

Nun möchten Sie für jedes Projekt in Ihrer Lösung Folgendes tun:

  1. Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Projekt entladen
  2. Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Bearbeiten Sie Ihre-xxx.csproj
  3. Suchen Sie nach Verweisen auf\packages\und aktualisieren Sie sie auf den neuen Speicherort.
    • Die meisten davon sind <HintPath> -Verweise, aber nicht alle. WebGrease und Microsoft.Bcl.Build verfügen beispielsweise über separate Pfadeinstellungen, die aktualisiert werden müssen.
  4. Speichern Sie die .csproj-Datei, klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Projekt neu laden

Sobald alle Ihre .csproj-Dateien aktualisiert wurden, starten Sie ein weiteres Rebuild All und Sie sollten keine Build-Fehler mehr wegen fehlender Referenzen haben. An diesem Punkt sind Sie fertig und haben NuGet für die Verwendung eines freigegebenen Paketordners konfiguriert.

Ab NuGet 2.7.1 (2.7.40906.75) mit VStudio 2012

Zunächst ist zu beachten, dass nuget.config nicht alle Pfadeinstellungen im Nuget-Paketsystem steuert. Dies war besonders verwirrend, um herauszufinden. Insbesondere besteht das Problem darin, dass msbuild und Visual Studio (das msbuild aufruft) den Pfad in nuget.config nicht verwenden, sondern ihn in der Datei nuget.targets überschreiben.

Umgebungsvorbereitung

Zuerst würde ich den Ordner Ihrer Lösung durchsuchen und alle vorhandenen\packages\-Ordner entfernen. Auf diese Weise stellen Sie sicher, dass alle Pakete sichtbar im richtigen Ordner installiert werden, und helfen Ihnen, fehlerhafte Pfadverweise in Ihren Lösungen zu finden. Als nächstes würde ich sicherstellen, dass Sie die neueste Nuget Visual Studio-Erweiterung installiert haben. Ich würde auch sicherstellen, dass Sie die neueste nuget.exe in jeder Lösung installiert haben. Öffnen Sie eine Eingabeaufforderung, wechseln Sie in jeden Ordner $ (SolutionDir)\.nuget\und führen Sie den folgenden Befehl aus:

nuget update -self

Festlegen des gemeinsamen Paketordnerpfads für NuGet

Öffnen Sie jedes $ (SolutionDir)\.nuget\NuGet.Config und fügen Sie im Abschnitt <configuration> Folgendes hinzu:

<config>
    <add key="repositorypath" value="$\..\..\..\Packages" />
</config>

Hinweis: Sie können einen absoluten Pfad oder einen relativen Pfad verwenden. Denken Sie daran, wenn Sie einen relativen Pfad mit $ verwenden, der relativ zu einer Ebene unter der Position von NuGet.Config ist (glauben Sie, dass dies ein Fehler ist).

Festlegen des gemeinsamen Paketordnerpfads für MSBuild und Visual Studio

Öffnen Sie jedes $ (SolutionDir)\.nuget\NuGet.targets und ändern Sie den folgenden Abschnitt (beachten Sie, dass sich für Nicht-Windows ein weiterer Abschnitt darunter befindet):

<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
    <!-- Windows specific commands -->
    <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
    <PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
    <PackagesDir>$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
</PropertyGroup>

Aktualisiere PackagesDir auf

<PackagesDir>$([System.IO.Path]::GetFullPath("$(SolutionDir)\..\Packages"))</PackagesDir>

Hinweis: Der GetFullPath löst unseren relativen Pfad in einen absoluten Pfad auf.

Wiederherstellen aller Nuget-Pakete in einem gemeinsamen Ordner

Öffnen Sie eine Eingabeaufforderung, gehen Sie zu $ ​​(SolutionDir)\.nuget und führen Sie den folgenden Befehl aus:

nuget restore ..\YourSolution.sln

Zu diesem Zeitpunkt sollten Sie einen einzelnen Ordner\packages\an Ihrem gemeinsamen Speicherort und keinen in einem Ihrer Lösungsordner haben. Wenn nicht, überprüfen Sie Ihre Pfade.

Projektreferenzen korrigieren

Öffnen Sie jede .csproj-Datei in einem Texteditor, suchen Sie nach Verweisen auf\packages und aktualisieren Sie sie auf den richtigen Pfad. Die meisten davon sind <HintPath> -Verweise, aber nicht alle. WebGrease und Microsoft.Bcl.Build verfügen beispielsweise über separate Pfadeinstellungen, die aktualisiert werden müssen.

Erstellen Sie Ihre Lösung

Öffnen Sie Ihre Lösung in Visual Studio und starten Sie einen Build. Wenn es sich über fehlende Pakete beschwert, die wiederhergestellt werden müssen, gehen Sie nicht davon aus, dass das Paket fehlt und wiederhergestellt werden muss (Fehler können irreführend sein). Es könnte ein fehlerhafter Pfad in einer Ihrer .csproj-Dateien sein. Überprüfen Sie dies zuerst, bevor Sie das Paket wiederherstellen.

Haben Sie einen Build-Fehler bezüglich fehlender Pakete?

Wenn Sie bereits überprüft haben, ob die Pfade in Ihren .csproj-Dateien korrekt sind, haben Sie zwei Möglichkeiten, dies zu versuchen. Wenn dies das Ergebnis der Aktualisierung Ihres Codes aus der Quellcodeverwaltung ist, können Sie versuchen, eine saubere Kopie auszuchecken und diese dann zu erstellen. Dies hat für einen unserer Entwickler funktioniert, und ich glaube, die .suo-Datei enthält ein Artefakt oder ähnliches. Die andere Möglichkeit besteht darin, eine Paketwiederherstellung manuell über die Befehlszeile im Ordner .nuget der betreffenden Lösung zu erzwingen:

nuget restore ..\YourSolution.sln
138
Vermis

Anstatt den allgemeinen Paketspeicherort für alle Projekte festzulegen, können Sie HintPath auch wie folgt im Projekt ändern:

<HintPath>$(SolutionDir)\packages\EntityFramework.6.1.0\lib\net40\EntityFramework.dll</HintPath>

In den meisten Fällen gibt es in einem freigegebenen Projekt nur wenige Pakete, sodass Sie es leicht ändern können.

Ich denke, es ist eine bessere Lösung. Wenn Sie Code verzweigen, wenn Sie das allgemeine Repo festlegen, müssen Sie den relativen Pfad ändern. In dieser Lösung müssen Sie dies nicht tun.

37
Adam Wyżgoł

Meine Erfahrung habe ich mit der neuesten Version von NuGet (2.7) und VS2012 versucht:

  • Löschen Sie den .nuget-Ordner (auf der Festplatte und in Lösung)
  • Fügen Sie eine NuGet.Config-Datei in einen gemeinsamen übergeordneten Ordner aller Lösungen ein
  • Löschen Sie alle vorhandenen Paketordner
  • Durchsuchen Sie alle csproj-Dateien und ändern Sie HintPaths so, dass sie auf den neuen Speicherort verweist
  • Profitieren

In meinem Fall wollte ich alle Pakete in .packages einfügen, sodass meine NuGet.Config wie folgt aussieht. 

 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
   <config>
     <add key="repositorypath" value=".packages" />
   </config>
 </configuration>

Beachten Sie, dass es einige "seltsame" Dinge gibt, die passieren können, aber ich denke, dass sie erträglich sind: 

  • Wenn Sie ein Paket von einer Lösung aus "aktualisieren", wird die ältere Version umgehend aus Ihrem Paketordner gelöscht (es kann nicht wissen, ob eine andere Lösung darauf verweist). Dies stört mich nicht sehr, da die andere Lösung bei Bedarf nur wiederhergestellt wird.
  • Wenn Sie versuchen, ein Paket aus einer Rechtsklick-Lösung hinzuzufügen, wenn das Paket bereits in einer anderen Lösung vorhanden ist, wird es dort angezeigt und es wird das grüne Häkchen anstelle der Schaltfläche "Installieren" angezeigt. Ich installiere normalerweise von einem Rechtsklick-Projekt, das stört mich also überhaupt nicht.

Disclaimer : Ich habe es gerade heute ausprobiert, ich habe keine langjährige Erfahrung, um es zu sichern!

20
Benjol

Ich habe NuGet Version 2.8.50926 mit VS 2013. Sie müssen nicht mehrere nuget.config-Dateien verwenden oder komplexe Verzeichnisstrukturen verwenden. Ändern Sie einfach die Standarddatei, die sich hier befindet:

%APPDATA%\Roaming\NuGet\NuGet.Config

Hier ist der Inhalt meiner Datei:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="repositoryPath" value="C:\Projects\nugetpackages" />
  </config>
  <activePackageSource>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
  </activePackageSource>
</configuration>

Daher gehen alle Pakete in den Ordner "C:\Projects\nugetpackages", unabhängig davon, wo sich die Lösung befindet.

Löschen Sie in allen Ihren Lösungen einfach vorhandene "Paket" -Ordner. Dann erstellen Sie Ihre Lösung und NuGet stellt die fehlenden Pakete automatisch in dem neuen, zentralisierten Verzeichnis wieder her, das Sie angegeben haben.

18
Matthieu

Nuget.targets muss bereits nicht geändert werden. Es wurde in nuget 2.8 ( http://nuget.codeplex.com/workitem/2921 ) behoben. Sie müssen nur Repositorypath einstellen.

8
daniel

Ich habe ein NuGet-Paket zusammengestellt, das alle NuGet-Referenzen in einem Projekt transparent in ein $ (SolutionDir) -relatives Format konvertiert. Dabei wird die XSLT-Transformation für die Buildzeit verwendet, sodass Sie Ihre Projektdatei nicht manuell hacken müssen. Sie können Ihre Pakete frei aktualisieren, es wird nichts kaputt gehen.

https://www.nuget.org/packages/NugetRelativeRefs

Wenn Sie Visual Studio 2015 Update 3 verwenden, können Sie die Paketreferenzen einfach wie hier beschrieben in project.json-Formular migrieren: https://oren.codes/2016/02/08/project-json-all- die Dinge

3
Oleg Tarasov

Von Visual Studio 2013 Update 4 und Version Nugget Package Manager> 2.8.5 ...

Erstellen Sie die Datei nuget.config im Stammverzeichnis des Repositorys.

dateiinhalt:

<configuration>
  <config>
    <add key="repositoryPath" value="packages" />
  </config>
  <packageSources>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
  </packageSources>
</configuration>

Dies führt dazu, dass alle Pakete auf der Ebene der Datei nuget.config des Pakets abgelegt werden.

Jetzt können Sie für jede .sln-Nuget-Konsole mit dem Befehl 'update-package -reinstall' gehen.

Wenn Sie über mehrere Repositorys auf derselben Ebene verfügen und denselben Paketordner für alle freigeben möchten, verwenden Sie die Möglichkeit, einen Ordner nach oben zu verschieben. 

 <add key="repositoryPath" value="..\packages" />

Auf diese Weise bewirken Sie, dass Nuget-Pakete auf den Ordner csproj verweisen, der einen Ordner nach oben in den Repository-Pfad zeigt.

3
user

Für jede wichtige Lösung werden die obigen Antworten nicht ausreichen. Eine komplexe TFS-Workspace-Struktur mit unterschiedlichen relativen Pfaden, Verzweigungen, gemeinsamen Projekten usw. macht ein zentrales Repository unmöglich. 

Die Verwendung von ($ SolutionDir) ist ein Schritt in die richtige Richtung, aber das manuelle Codieren der csproj-Datei mit ($ SolutionDir) würde in einer Codebasis mit hunderten von Paketen, die regelmäßig aktualisiert werden, recht langwierig werden (bei jedem Update wird der HintPath überschrieben ein neuer relativer Pfad). Was passiert, wenn Sie Update-Package -Reinstall ausführen müssen?.

Es gibt eine großartige Lösung namens NugetReferenceHintPathRewrite . Es automatisiert die Injektion von ($ SolutionDir) in die HintPaths direkt vor dem Build (ohne die csproj-Datei tatsächlich zu ändern). Ich kann mir vorstellen, dass es leicht in automatisierte Build-Systeme integriert werden könnte 

2
gravidThoughts

Einfach Hardlink/Pakete zum gewünschten gemeinsam genutzten Ort. Ihr Projekt wird dann für andere Benutzer, die keinen speziellen Speicherort für Pakete haben, nicht beschädigt. 

Öffnen Sie eine Eingabeaufforderung als Admin und verwenden Sie sie

mklink /prefix link_path Target_file/folder_path
2
user803469

Aktualisierung meiner Erfahrungen mit Nuget 2.8.3. Es war relativ einfach. Alles, was getan wurde, war enabled package restore von der Rechtsklicklösung. Editierte NuGet.Config und fügte folgende Zeilen hinzu:

  <config>
    <add key="repositorypath" value="..\Core\Packages" />
  </config>

Anschließend wurde die Lösung neu aufgebaut, alle Pakete wurden in den gewünschten Ordner heruntergeladen und die Referenzen automatisch aktualisiert. Das habe ich auch für alle meine anderen Projekte getan, bei denen nur inkrementelle Pakete heruntergeladen und auf vorhandene Pakete verwiesen wurde. Daher wurde ein gemeinsames Paket-Repository für alle Projekte festgelegt.

Hier finden Sie eine schrittweise Anleitung zum Aktivieren der Wiederherstellung von Paketen.

http://blogs.4ward.it/enable-nuget-package-restore-in-visual-studio-and-tfs-2012-rc-to-building-windows-8-metro-apps/

2

Eine kurze Zusammenfassung für diejenigen auf VS 2013 professional mit NuGet Version: 2.8.60318.667

So würden Sie Pakete an einen Pfad relativ zum Ordner .nuget weiterleiten:

<configuration>
  <config>
    <add key="repositoryPath" value="../Dependencies" />
  </config>
</configuration>

Wenn sich Ihre Lösung (.sln-Datei) beispielsweise in C:\Projects\MySolution befindet, wird der Ordner .nuget beim Aktivieren der Wiederherstellung des NuGet-Pakets folgendermaßen erstellt: C:\Projects\MySolution.nuget und die Pakete werden heruntergeladen in ein Verzeichnis wie folgt: C:\Projects\MySolution\Dependencies

HINWEIS: Aus irgendeinem (unbekannten) Grund muss ich jedes Mal, wenn ich den "RepositoryPath" aktualisiere, die Lösung schließen und erneut öffnen, damit die Änderungen wirksam werden

1

für diejenigen, die Paket als Paketmanager verwenden, gibt es eine Auto-Symlink-Option für Ihre Abhängigkeitsdatei:

storage: symlink

btw: paket nutzt nuget

referenz: https://fsprojects.github.io/Paket/dependencies-file.html

Wenn Sie so wenig wie möglich ändern möchten, können Sie die Unterverzeichnisse regelmäßig mit einem Skript bereinigen. dh. Das Standardverhalten von Nuget ist das Kopieren von Dateien von einem globalen Speicherort in einen lokalen Paketordner. Löschen Sie diese Dateien anschließend.

0
sgtz