Wie fügen Sie zusätzliche Dateien mithilfe von VS2010-Webbereitstellungspaketen hinzu?

125

Ich teste die neuen Web-Packaging-Funktionen in Visual Studio 2010 und bin auf eine Situation gestoßen, in der ich mithilfe eines Pre-Build-Ereignisses die erforderlichen DLLs in meinen bin-Ordner kopiere, auf den sich meine App für API-Aufrufe stützt. Sie können nicht als Referenz aufgenommen werden, da es sich nicht um COM-DLLs handelt, die mit Interop verwendet werden können.

Wenn ich mein Bereitstellungspaket erstelle, werden diese Dateien ausgeschlossen, wenn ich die Option wähle, nur die Dateien einzuschließen, die zum Ausführen der App erforderlich sind. Gibt es eine Möglichkeit, die Bereitstellungseinstellungen so zu konfigurieren, dass sie diese Dateien enthalten? Ich hatte kein Glück, eine gute Dokumentation dazu zu finden.

Jason
quelle

Antworten:

176

Gute Frage. Ich habe gerade einen sehr detaillierten Blogeintrag dazu im Web Deployment Tool (MSDeploy) veröffentlicht: Build Package mit zusätzlichen Dateien oder ohne bestimmte Dateien .

Hier ist die Zusammenfassung. Nachdem ich Dateien eingeschlossen habe, zeige ich, wie man auch Dateien ausschließt.

Einschließlich zusätzlicher Dateien

Das Einfügen zusätzlicher Dateien in das Paket ist etwas schwieriger, aber immer noch kein Problem, wenn Sie mit MSBuild vertraut sind und wenn Sie dies nicht tun, lesen Sie dies. Dazu müssen wir uns in den Teil des Prozesses einbinden, der die Dateien zum Verpacken sammelt. Das Ziel, das wir erweitern müssen, heißt CopyAllFilesToSingleFolder. Dieses Ziel verfügt über die Abhängigkeitseigenschaft PipelinePreDeployCopyAllFilesToOneFolderDependsOn, die wir abrufen und in unser eigenes Ziel einfügen können. Also werden wir ein Ziel namens CustomCollectFiles erstellen und dieses in den Prozess einfügen. Dies erreichen wir mit folgendem (denken Sie nach der Importanweisung daran).

<PropertyGroup>
  <CopyAllFilesToSingleFolderForPackageDependsOn>
    CustomCollectFiles;
    $(CopyAllFilesToSingleFolderForPackageDependsOn);
  </CopyAllFilesToSingleFolderForPackageDependsOn>

  <CopyAllFilesToSingleFolderForMsdeployDependsOn>
    CustomCollectFiles;
    $(CopyAllFilesToSingleFolderForMsdeployDependsOn);
  </CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>

Dadurch wird unser Ziel zum Prozess hinzugefügt. Jetzt müssen wir das Ziel selbst definieren. Angenommen, Sie haben einen Ordner mit dem Namen "Zusätzliche Dateien", der sich 1 Ebene über Ihrem Webprojekt befindet. Sie möchten alle diese Dateien einschließen. Hier ist das CustomCollectFiles-Ziel, das wir anschließend diskutieren.

<Target Name="CustomCollectFiles">
  <ItemGroup>
    <_CustomFiles Include="..\Extra Files\**\*" />

    <FilesForPackagingFromProject  Include="%(_CustomFiles.Identity)">
      <DestinationRelativePath>Extra Files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
    </FilesForPackagingFromProject>
  </ItemGroup>
</Target>

Hier habe ich das Element _CustomFiles erstellt und im Include-Attribut angewiesen, alle Dateien in diesem Ordner und alle darunter liegenden Ordner aufzunehmen. Wenn von einer Chance müssen Sie ausschließen etwas aus dieser Liste, fügen Sie ein ExcludeAttribut zu _CustomFiles.

Dann benutze ich dieses Element, um das FilesForPackagingFromProject-Element zu füllen. Dies ist das Element, mit dem MSDeploy tatsächlich zusätzliche Dateien hinzufügt. Beachten Sie auch, dass ich den Metadaten-Wert DestinationRelativePath deklariert habe. Dies bestimmt den relativen Pfad, den es in das Paket einfügen wird. Ich habe hier die Anweisung Extra Files% (RecursiveDir)% (Filename)% (Extension) verwendet. Das heißt, Sie platzieren es an derselben relativen Position im Paket wie im Ordner "Zusätzliche Dateien".

Dateien ausschließen

Wenn Sie die Projektdatei einer mit VS 2010 erstellten Webanwendung unten öffnen, finden Sie eine Zeile mit.

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

Übrigens können Sie die Projektdatei in VS öffnen. Klicken Sie mit der rechten Maustaste auf das Projekt und wählen Sie Projekt entladen. Klicken Sie dann mit der rechten Maustaste auf das entladene Projekt und wählen Sie Projekt bearbeiten.

Diese Erklärung enthält alle Ziele und Aufgaben, die wir benötigen. Die meisten unserer Anpassungen sollten nach diesem Import erfolgen, wenn Sie nicht sicher sind, ob nachher! Wenn Sie also Dateien ausschließen müssen, gibt es einen Elementnamen, ExcludeFromPackageFiles, der dazu verwendet werden kann. Angenommen, Sie haben eine Datei mit dem Namen Sample.Debug.xml in Ihrer Webanwendung, möchten jedoch, dass diese Datei aus den erstellten Paketen ausgeschlossen wird. Sie können das Snippet unten nach dieser Importanweisung platzieren.

<ItemGroup>
  <ExcludeFromPackageFiles Include="Sample.Debug.xml">
    <FromTarget>Project</FromTarget>
  </ExcludeFromPackageFiles>
</ItemGroup>

Wenn Sie das Auffüllen dieses Elements deklarieren, werden die Dateien automatisch ausgeschlossen. Beachten Sie hier die Verwendung der FromTargetMetadaten. Ich werde hier nicht darauf eingehen, aber Sie sollten wissen, dass Sie das immer spezifizieren müssen.

Sagte Ibrahim Hashimi
quelle
3
Könnten Sie Ihr Beispiel erweitern, um zusätzliche Projektausgaben in die Veröffentlichung aufzunehmen?
Anthony Serdyukov
7
Ich habe VS2012 (RC) installiert und für mich gab es eine andere DependencyProperty. Um gemischte Teams (und unseren Build-Server) zu unterstützen, hatte ich die ursprüngliche CopyAllFilesToSingleFolderForPackageDependsOn-Konfiguration und ein Duplikat mit der DependencyProperty CopyAllFilesToSingleFolderForMsdeployDependsOn
Emil Lerch
2
Das ist wunderbar. Verwenden Sie diese Option, um einige Versionsinformationen bereitzustellen, die in einer txt-Datei gespeichert sind.
Lamarant
5
Das scheint bei mir nicht zu funktionieren. Ich verwende VStudio 2013. :( Funktioniert das obige MSbuild-Setup für 2013?
Irperez
8
@ SayedIbrahimHashimi und Co. haben eine viel aktuellere Version dieses Handbuchs auf der asp.net-Website erstellt . Ich kann diesen Link nur empfehlen, da dies der Unterschied zwischen mir und dem Ändern der csproj-Datei anstelle der pubxml-Datei war.
Adam Venezia
21

Eine einfachere Lösung besteht darin, die csproj-Datei so zu bearbeiten, dass die erforderliche DLL in den Ordner bin aufgenommen wird, und dann ein Ziel vor dem Erstellen zu erstellen, um das Element aus dem allgemeinen Bibliotheksordner, in dem wir unsere DLLs von Drittanbietern speichern, in den Ordner bin zu kopieren. Da das Element in der Lösungsdatei vorhanden ist, wird es von msbuild / msdeploy bereitgestellt und es ist nichts Kompliziertes erforderlich.

Tag, das zum Einschließen von Dateien ohne Hinzufügen über VS verwendet wird (das normalerweise zu Ihrem VCS hinzugefügt werden soll)

<Content Include="Bin\3rdPartyNative.dll" ><Visible>false</Visible></Content>

Dies ist das BeforeBuild-Ziel, das für mich funktioniert hat:

<Target Name="BeforeBuild">
    <Message Text="Copy $(SolutionDir)Library\3rdPartyNative.dll to '$(TargetDir)'3rdPartyNative.dll" Importance="high" />
    <Copy SourceFiles="$(SolutionDir)Library\3rdPartyNative.dll" DestinationFiles="$(TargetDir)3rdPartyNative.dll" />
</Target>

Bearbeitet, um den Vorschlag von @ tuespetre aufzunehmen, den Eintrag auszublenden, wodurch der vorherige Nachteil eines sichtbaren Bin-Ordners entfernt wird. Von mir nicht bestätigt.

toxaq
quelle
3
"Einfachheit ist die ultimative Raffinesse"
BornToCode
1
Dies funktioniert in vielen Fällen, aber nicht, wenn Sie Dateien haben, die außerhalb des bin-Ordners enthalten sein müssen.
Nathan
5
@toxaq, ich könnte etwas fehle, aber das Problem war ich festgestellt , dass ich tatsächlich benötigen die Dateien in einem Ort in dem Bereitstellungspaket , das war nicht im Ordner ist. Ja, Sie können die Dateien von überall in den Ordner bin kopieren, aber sie werden in diesem Szenario nicht an der richtigen Stelle im Bereitstellungspaket enthalten sein. Die Situation, auf die ich gestoßen bin, war das ClearScript.V8-Projekt - die nativen DLLs dürfen nicht im bin-Verzeichnis, sondern im übergeordneten Verzeichnis angezeigt werden - siehe clearscript.codeplex.com/discussions/438696 für die Diskussion .
Nathan
3
Ich würde noch zehn Mal upvoten, wenn ich könnte. Dies sollte die akzeptierte Antwort sein. Ich möchte auch hinzufügen, dass Sie festlegen können, dass <Visible>false</Visible>es vor dem Projektmappen-Explorer ausgeblendet wird.
Dienstag,
1
@Thid danke, habe das bearbeitet. Ich habe kein MS-Zeug zum Testen, daher habe ich es nicht überprüft.
Toxaq
7

Genau wie @toxaq, aber eine noch einfachere Lösung ist:

Fügen Sie im Lösungs-Explorer die Datei als Link zum Ordner "Bibliothek / Referenzen" hinzu und legen Sie sie in den Eigenschaften so fest, dass sie in die Ausgabe des Builds kopiert wird.

eglasius
quelle
2
-1 Dies setzt voraus, dass das Projekt eine explizite Linker-Zeit-Beziehung haben möchte. Nicht geeignet für Plug-In-Systeme
MickyD
6

Die Implementierung von Sayed hat bei mir also nicht funktioniert. Ich verwende VS2013 und das Web Deploy-Paket und musste einige Plugin-DLLs aus einem anderen Ordner in den Bin des Deployment-Pakets einfügen. So habe ich es geschafft (viel einfacher):

Fügen Sie am Ende Ihrer csproj-Datei Folgendes hinzu:

<Target Name="AdditionalFilesForPackage" AfterTargets="CopyAllFilesToSingleFolderForMsdeploy">
    <ItemGroup> 
        <Files Include="..\SomeOtherProject\bin\$(Configuration)\*.*"/>
    </ItemGroup>
    <Copy SourceFiles="@(Files)" DestinationFolder="$(_PackageTempDir)\bin\" />  
</Target>

Weitere Erwähnungen in der csproj-Datei:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <DeployOnBuild>true</DeployOnBuild>
    <DeployTarget>Package</DeployTarget>
    <DeployIisAppPath>Default Web Site/MyWebsite</DeployIisAppPath>
    <DesktopBuildPackageLocation>..\output\Service\Service\Service.Release.zip</DesktopBuildPackageLocation>
    <FilesToIncludeForPublish>OnlyFilesToRunTheApp</FilesToIncludeForPublish>
    <ExcludeGeneratedDebugSymbol>true</ExcludeGeneratedDebugSymbol>
    <PublishDatabases>false</PublishDatabases>
</PropertyGroup>

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0\WebApplications\Microsoft.WebApplication.targets" />
K0D4
quelle
Danke dir. Ich verwende VS2015 und musste auch DLLS aus einem anderen Projekt-Bin-Ordner hinzufügen. Ihre Lösung war die einfachste und funktionierte einwandfrei.
Rafael
5

Wollte einen Kommentar abgeben, um den obigen Kommentar von Emil Lerch hervorzuheben. Wenn Sie ein Azure SDK installiert haben, suchen Sie nach einer anderen DependencyProperty.

Grundsätzlich müssen Sie möglicherweise "CopyAllFilesToSingleFolderForMsdeployDependsOn" anstelle von "CopyAllFilesToSingleFolderForPackageDependsOn" verwenden. Ich bin kein fortgeschrittener MsBuild-Typ und habe Stunden damit verbracht, herauszufinden, warum meine Ziele nicht aufgerufen wurden.

Hier ist ein weiterer Link, wenn dies für Sie nicht funktioniert und Sie ein Azure SDK installiert haben: http://forums.iis.net/t/1190714.aspx

Paul Schroeder
quelle
3

Als Ergänzung zu Sayeds Antwort stellte ich fest, dass eine statische Deklaration von ExcludeFromPackageFiles-Elementen in meinem Projekt nicht ausreichte. Ich musste bestimmte DLLs ausschließen, die erst nach dem Kompilieren verfügbar waren (Azure-spezifische Ninject-Module, die bei der Bereitstellung auf IIS nicht benötigt werden).

Also habe ich versucht, meine ExcludeFromPackageFiles-Liste mit dem oben angegebenen Trick CopyAllFilesToSingleFolderForPackageDependsOn zu generieren. Dies ist jedoch zu spät, da der Verpackungsprozess die ExcludeFromPackageFiles-Elemente bereits entfernt hat. Also habe ich die gleiche Technik angewendet, aber etwas früher:

<PropertyGroup>
    <ExcludeFilesFromPackageDependsOn>
        $(ExcludeFilesFromPackageDependsOn);
        _ExcludeAzureDlls
    </ExcludeFilesFromPackageDependsOn>
</PropertyGroup>

<Target Name="_ExcludeAzureDlls">
    <ItemGroup>
        <FilesForPackagingFromProjectWithNoAzure Include="@(FilesForPackagingFromProject)"
                               Exclude="%(RootDir)%(Directory)*Azure*.dll" />
        <AzureFiles Include="@(FilesForPackagingFromProject)"
                    Exclude="@(FilesForPackagingFromProjectWithNoAzure)" />
        <ExcludeFromPackageFiles Include="@(AzureFiles)">
            <FromTarget>_ExcludeAzureEnvironmentDlls</FromTarget>
        </ExcludeFromPackageFiles>
    </ItemGroup>
</Target>

Hoffe das hilft jemandem ...

Peter McEvoy
quelle
1

Es ist auch möglich, die Datei als Inhalt | festzulegen Immer kopieren

Es ist auch möglich, die Datei als Inhalt | festzulegen  Immer kopieren

Fabito
quelle
1
Dies scheint die beste Antwort zu sein, da dies die einfachste und offensichtlichste ist
J Miglietta