Wie kann ich dafür sorgen, dass mein verwaltetes NuGet-Paket C ++ / CLI-Projekte unterstützt?

74

Ich habe ein NuGet-Paket erstellt, das gut funktioniert, wenn ich es aus einem C # -Projekt verwende. Es enthält eine DLL im lib/net40Verzeichnis und die DLL wird als Referenz hinzugefügt.

Wie ändere ich mein Paket, nachdem NuGet C ++ unterstützt, so, dass die DLL als verwaltete Referenz in einem C ++ / CLI-Projekt hinzugefügt werden kann? Ich kann keine Tutorials finden, die dies erklären. Wenn ich versuche, das Paket so wie es ist hinzuzufügen, erhalte ich die folgende Fehlermeldung:

Sie versuchen, dieses Paket in einem Projekt zu installieren, das auf "Native, Version = v0.0" abzielt, aber das Paket enthält keine Assemblyreferenzen oder Inhaltsdateien, die mit diesem Framework kompatibel sind.

Man könnte meinen, dass die Lösung darin besteht, die Dateien unter lib / native abzulegen, aber laut http://docs.nuget.org/docs/reference/support-for-native-projects wird dies nicht unterstützt. Außerdem scheint es nichts zu bewirken, die DLL einfach direkt unter lib zu stellen.

Anscheinend soll ich dies mit einer .propsoder .targets-Datei unter build / native tun, aber was muss ich in diese Dateien einfügen, damit dies funktioniert?

Tor Hovland
quelle
5
Ich sehe dies eher als Fehler in NuGet als als etwas, das Sie in Ihrem Paket anpassen müssen. Siehe dies: nuget.codeplex.com/workitem/3665 Auch diese Frage ist verwandt: stackoverflow.com/q/18786338/289770
Yodan Tauber
Vielen Dank! Komisch, wie der Fehlerbericht am Tag nach meiner Frage veröffentlicht wurde. Ich habe jetzt dafür gestimmt. Trotzdem, Fehler oder kein Fehler, ich glaube, dass es möglich ist, dies mit NuGet-Skripten zu lösen, und ich suche nach einer Anleitung, die genau das tut.
Tor Hovland
1
10 Monate später, aber vielleicht hilft Ihnen dies ([ stackoverflow.com/questions/23571241/… ). [1]: stackoverflow.com/questions/23571241/…
clairestreb

Antworten:

31

Wie Patrick O'Hara schrieb , wird NuGet für Sie keine Änderungen an einem C ++ / CLI-Projekt vornehmen. Siehe GitHub-Problem NuGet / Home # 1121 - Verwaltete Pakete können nicht in ein CLI-Projekt installiert werden . Mit dem NuGet-Befehlszeilenprogramm NuGet.exekönnen Sie NuGet jedoch die gewünschten Pakete herunterladen und entpacken lassen.

Als vollständiges Beispiel habe ich folgende Schritte ausgeführt, um einen Verweis auf OptimizedPriorityQueue 1.0.0 in einem Visual Studio 2013 C ++ / CLI-Projekt hinzuzufügen :

  1. Öffnen Sie die Package Manager-Konsole, falls sie noch nicht geöffnet ist ( TOOLS> NuGet Package Manager> Package Manager-Konsole ).
  2. Installieren Sie in der Package Manager-Konsole das NuGet.CommandLine-Paket:

    Install-Package NuGet.CommandLine
    

    (Hinweis: Zum jetzigen Zeitpunkt ist die neueste Version von NuGet.CommandLine 2.8.6. Dies kann für Sie anders sein.)

  3. In Ihrem Projektordner sollte sich jetzt eine .nuget\packages.configXML-Datei mit folgendem Inhalt befinden:

    <?xml version="1.0" encoding="utf-8"?>
    <packages>
      <package id="NuGet.CommandLine" version="2.8.6" />
    </packages>
    
  4. Fügen Sie in einem Texteditor wie Notepad ++ ein <package>Element für das gewünschte Paket hinzu. In diesem Fall habe ich hinzugefügt:

    <package id="OptimizedPriorityQueue" version="1.0.0" />
    

    .. innerhalb des <packages>Elements.

  5. Öffnen Sie eine Eingabeaufforderung (Ich habe eine VS2013 Developer-Eingabeaufforderung geöffnet, aber eine reguläre Eingabeaufforderung sollte funktionieren.)

  6. cd in den Projektordner.
  7. Führen Sie den folgenden Befehl aus und ändern Sie die Versionsnummer von NuGet.CommandLine, falls abweichend:

    . \ packages \ NuGet.CommandLine.2.8.6 \ tools \ NuGet.exe Installieren Sie -NonInteractive -OutputDirectory-Pakete .nuget \ packages.config
    

    Für mich war die Ausgabe:

    Installieren von 'OptimizedPriorityQueue 1.0.0.0'.
    'OptimizedPriorityQueue 1.0.0.0' wurde erfolgreich installiert.
    Alle in packages.config aufgelisteten Pakete sind bereits installiert.
    
  8. Klicken Sie mit der rechten Maustaste auf das Projekt in Visual Studio und wählen Sie Eigenschaften . Klicken Sie unter Allgemeine Eigenschaften> Referenzen auf die Schaltfläche Neue Referenz hinzufügen.
  9. Wählen Sie auf der linken Seite Durchsuchen . Neben den Schaltflächen OK und Abbrechen des Dialogfelds Referenz hinzufügen befindet sich die Schaltfläche Durchsuchen… . Klicken Sie darauf, um einen Dateiauswahldialog zu öffnen.
  10. Navigieren Sie zu den DLLs, die NuGet in das packagesUnterverzeichnis Ihres Projektordners entpackt hat, und klicken Sie auf die Schaltfläche Hinzufügen . Klicken Sie auf OK , um das Dialogfeld Referenz hinzufügen zu schließen.
  11. Sie sollten nun in der Lage sein, die Assembly in Ihrem C ++ / CLI-Projekt zu verwenden:

    using namespace Priority_Queue;
    
    //...
    
Daniel Trebbien
quelle
@ daniel-trebbien, wie gehst du mit paketaktualisierungen um?
CodeFox
5
@ daniel-trebbien, irgendwelche Hinweise, wie die Schritte 8 bis 10 in Visual Studio 2017 funktionieren?
Michał Fita
Dies hat in Visual Studio 2013 sehr gut funktioniert. Diese Lösung hat mir besser gefallen als das Erstellen eines C # -Dummy-Projekts und das Kopieren von DLLs von einem Projekt in ein anderes. Ich konnte NLog 4.0.0 hinzufügen.
Charles Owen
Sehr hilfreich, danke! Zu Ihrer Information, als ich dies in VS 2019 tat, musste ich den Befehl für Schritt 7 geringfügig ändern. Die Datei packages.config wurde im Basisverzeichnis des Projekts erstellt, nicht in einem .nuget-Ordner. Um "Durchsuchen" als Option in Schritt 8 zu sehen, musste ich sicherstellen, dass mein Projekt für "Common Language Runtime Support (/ clr)" konfiguriert war. Hth, X
Xeozim
7

Es scheint tatsächlich eine Möglichkeit zu geben, die Installation und automatische Referenzierung "regulärer" NuGet-Pakete aus C ++ / CLI-Projekten mithilfe der folgenden Schritte (zumindest mit NuGet >= 2.5) zu ermöglichen:

  1. Fügen Sie build\<ProjectName>.targetsIhrem zu verpackenden Projekt eine Datei hinzu (oder ändern Sie sie), und fügen Sie folgenden Inhalt ein (stellen Sie sicher, dass Sie ihn <AssemblyName>durch einen tatsächlichen Wert ersetzen ):

    <?xml version="1.0" encoding="utf-8" ?>
    <Project ToolsVersion="4.0"
             xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <!-- for C++/CLI projects only -->
      <ItemGroup Condition="'$(Language)' == 'C++'">
        <Reference Include="<AssemblyName>">
          <!--
            this .targets file is installed next to the assembly,
            so we do not have to figure out any versions or paths here ourselves
          -->
          <HintPath>
            $(MSBuildThisFileDirectory)..\lib\native\<AssemblyName>.dll
          </HintPath>
        </Reference>
      </ItemGroup>
    </Project>
    
  2. In den .nuspecvon den verpackten Projekt auch einer oder mehr fileEinträgen auch die Montag in platzieren lib\native\Verzeichnis auf dem Zielcomputer:

    <package>
      <metadata>
        ...
      </metadata>
      <files>
        ...
        <!--
          add a copy of the assembly to lib\native to prevent NuGet
          from complaining about incompatible native projects
        -->
        <file src="bin\$configuration$\$id$.dll" target="lib\native\" />
        <file src="bin\$configuration$\$id$.xml" target="lib\native\" />
    
        <!-- don't forget about the .targets file containing the reference -->
        <file src="build\$id$.targets" target="build\" />
      </files>
      ...
    </package>
    

Auch wenn NuGet nicht hinzufügen Montag Verweise auf C ++ / CLI - Projekte, fügt sie noch jeden .propsund .targetsvon einem Paket bereitgestellt Dateien. Das benutzerdefinierte Ziel aus Schritt 1 fügt einen Verweis auf unsere verpackte Baugruppe hinzu.

Ein Nachteil dieser Lösung ist meines Erachtens , dass die so hinzugefügte Referenz nicht im Commpon Properties/Framework and ReferencesAbschnitt des C ++ / CLI-Projekts angezeigt wird . Es kann auch andere geben, verwenden Sie es also auf eigenes Risiko ...

Buygrush
quelle
6

Wie in der Antwort auf diesen Port erwähnt ( Nuget installiert Entity Framework nicht in einem C ++ / CLI-Projekt ), nimmt NuGet die Änderungen an einem C ++ / CLI-Projekt nicht für Sie vor. Es wird jedoch die Abhängigkeit für Sie herunterladen und entpacken. Wir verwenden es über die Befehlszeile als Teil unserer Make-Abhängigkeiten. Die Befehlszeile sieht ungefähr so ​​aus:

/.NuGet/NuGet.exe
      Install 
      -NonInteractive 
      -ConfigFile $ENV{SRC_ROOT}/.nuget/NuGet.config 
      -OutputDirectory $ENV{SRC_ROOT}/packages 
      $ENV{SRC_ROOT}/packages.config

Beachten Sie, dass die Befehlszeilenelemente eins zu einer Zeile getrennt sind, um das Lesen zu erleichtern. Außerdem haben wir uns entschlossen, NuGet in unsere Quellcodeverwaltung im Ordner .NuGet einzuchecken. Ziel war es, die Einrichtung einer Build-Maschine für unsere verschiedenen Umgebungen (von denen nicht alle Visual Studio verwenden) zu vereinfachen. Nachdem Sie diesen Befehl zum ersten Mal ausgeführt haben, müssen Sie die Abhängigkeiten manuell zu Ihrem C ++ / CLI-Projekt hinzufügen.
Hoffentlich hilft das.

Patrick O'Hara
quelle
Es sieht so aus, als ob mein C ++ / CLI-Projekt eine Klassenbibliothek (Assembly) anstelle einer Exe ist. Nuget schlägt immer noch fehl.
Weipeng L
@WeipengL Dies ist eine ziemlich alte Frage. Ihrer Antwort fehlen Details. Vielleicht sollten Sie eine neue Frage erstellen, die Ihr Problem beschreibt und sich auf diese Frage bezieht?
Patrick O'Hara
1

Das Installationsprogramm versucht, im C # -Startprojekt einen Verweis auf sich selbst hinzuzufügen. Machen Sie vor der Installation ein C # -Projekt zum Startprojekt in der Lösung. Erstellen Sie ein Dummy-C # -Projekt, falls Sie keines haben

Mikael
quelle
C # ist nicht dasselbe wie C ++ / CLI
rjzii
1

Eine einfache Problemumgehung besteht darin, ein solches NuGet in ein reguläres .NET-Projekt (C #) zu verpacken und in Ihrem C ++ / CLI-Projekt darauf zu verweisen.

Chandra
quelle
0

Die obigen Antworten haben Probleme mit Abhängigkeiten der zweiten Ebene (zumindest in meinem Fall unter Visual Studio 2019).

Um das Problem zu lösen, erstelle ich normalerweise eine leere c # -Konsolenanwendung und verweise dort auf alle Pakete.

Dann verwende ich dieses Post-Build-Snippet, um alles außer den Hauptartefakten des Projekts in einen gemeinsamen Speicher zu kopieren, der packagesim Lösungsordner benannt ist.

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <PropertyGroup>
      <SharedLibraries>$(SolutionDir)\packages</SharedLibraries>
    </PropertyGroup>

    <ItemGroup>
      <Artifacts Include="$(OutDir)\**" />
    </ItemGroup>

    <RemoveDir Condition=" Exists('$(SharedLibraries)')" Directories="$(SharedLibraries)" />
    <MakeDir Condition=" !Exists('$(SharedLibraries)')" Directories="$(SharedLibraries)" />

    <Copy SourceFiles="@(Artifacts)" DestinationFolder="$(SharedLibraries)\%(RecursiveDir)" />

    <ItemGroup>
      <ExtraFiles Include="$(SharedLibraries)\$(ProjectName).*"></ExtraFiles>
    </ItemGroup>

    <Delete Files="@(ExtraFiles)" />

  </Target>

Der gesamte packagesOrdner wird dann mit einer benutzerdefinierten Aufgabe im c ++ / cli-Projekt bereitgestellt.

Diese Lösung ist geeignet, wenn die Pakete, auf die verwiesen wird, auf etwas abzielen. AnyCPUAndernfalls ist etwas Basteln erforderlich, um unterschiedliche Ordner für jede Prozessorarchitektur zu verwenden, und funktioniert wahrscheinlich nicht.

Diese Lösung ist nicht elegant, löst jedoch den Zweck, Nuget-Pakete (indirekt) aus einem c ++ / cli-Projekt zuverlässig zu konsumieren.

Das Plus dieser Lösung gegenüber anderen hier veröffentlichten ist, dass die Pfade nicht versioniert sind, sodass C ++ / Cli-Projekte während des normalen Paket-Upgrades niemals geändert werden.

Yennefer
quelle
-7

Anmeldeinformationen werden tatsächlich mit dem Maschinenschlüssel verschlüsselt, auf dem die Paketquelle hinzugefügt wurde. Sofern nicht die Klartextvariante verwendet wird, sollte der Befehl setApiKey wahrscheinlich als Teil des Builds ausgeführt werden.

Omar H.
quelle