wake-up-neo.com

Wie kann TFS jedes Projekt in einem eigenen Verzeichnis ausgeben?

Ich füge eine große Codebasis in Team Foundation Server ein. Ich möchte, dass der Build-Prozess einen "ready-to-deploy" -Aufbau unserer Projekte erstellt.

Normalerweise tun wir dies, indem die Ausgabe jedes Projekts in einem eigenen Ordner abgelegt wird. So haben wir zum Beispiel so etwas wie

C:\project1\
            Assembly1.dll
            Assembly2.dll
            project1.exe
            project1.exe.config
C:\project2\
            Assembly2.dll
            Assembly3.dll
            project2.exe
            project2.exe.config
C:\project3\
            Assembly1.dll
            Assembly3.dll
            project3.exe
            project3.exe.config

So mögen wir es.

TFS scheint jedoch alles im selben Verzeichnis zu speichern.

C:\output\
          Assembly1.dll
          Assembly2.dll
          Assembly3.dll
          project1.exe
          project1.exe.config
          project2.exe
          project2.exe.config
          project3.exe
          project3.exe.config

das spart zwar etwas Speicherplatz (die Assemblys sind nur jeweils einmal dort), aber wir wollen es nicht. 

Wie können Sie am besten angeben, wo TFS/MSBuild die Ausgabedateien ablegen soll? Muss ich die sln/csproj-Dateien einzeln bearbeiten, um dies zu erreichen, oder kann ich das in der Datei TFSBuild.proj tun? (d. h. in einer MSBuild-spezifischen Datei)

57
Tom Kidd

Ich habe hier gerade eine andere Methode gebloggt:

http://mikehadlow.blogspot.com/2009/06/tfs-build-publishedwebsites-for-exe-and.html Wenn Sie jedoch nicht auf den Link folgen möchten, ist dies der Fall vollständig:

Im Allgemeinen ist es eine gute Praxis, den gesamten Code, der unter der Kontrolle Ihres Teams steht, in einer einzigen Uber-Lösung zu sammeln, wie in diesem PDFs zu Patterns and Practices, Team Development with TFS Guide, beschrieben. Wenn Sie dann den TFS-Build-Server für die Erstellung dieser Lösung konfigurieren, wird die Build-Ausgabe standardmäßig in einem einzigen Ordner ("Release") abgelegt.

Alle Webanwendungsprojekte in Ihrer Lösung werden auch in einem Ordner namens _PublishedWebsites\ausgegeben. Das ist sehr schön, denn Sie können die Webanwendung einfach durch Robocopy bereitstellen.

Leider gibt es kein ähnliches Standardverhalten für andere Projekttypen wie WinForms, Konsole oder Bibliothek. Es wäre sehr schön, wenn wir einen _PublishedApplications\-Unterordner mit der Ausgabe eines ausgewählten Projekts haben könnten. Zum Glück ist das gar nicht so schwer.

Die Funktionsweise von _PublishedWebsites ist ziemlich einfach. Wenn Sie sich die Projektdatei Ihrer Webanwendung ansehen, werden Sie unten einen Import feststellen:

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

Auf meinem Computer wird die MSBuildExtensionsPath-Eigenschaft in C:\Programme\MSBuild ausgewertet. Wenn Sie die Datei Microsoft.WebApplication.targets öffnen, können Sie feststellen, dass es sich um eine ziemlich einfache MSBuild-Datei handelt, die erkennt, wenn der Build kein Desktop-Build ist, d. H TFS build und kopiert die Ausgabe nach:

$(OutDir)_PublishedWebsites\$(MSBuildProjectName)

Ich habe einfach die Datei Micrsoft.WebApplication.targets kopiert, mit einem relativen Pfad aus meinen Projektdateien unter Quellcodeverwaltung versetzt, _PublishedWebsites in _PublishedApplications geändert und die Datei in CI.exe.targets umbenannt. Für jedes Projekt, das ich in _PublishedApplications ausgeben möchte, habe ich diesen Import einfach am Ende der Projektdatei hinzugefügt:

<Import Project="<your relative path>\CI.exe.targets" />

Sie können CI.exe.targets (oder wie auch immer Sie es nennen möchten) bearbeiten, um Ihre Gebote abzugeben. In meinem Fall besteht die einzige Änderung bisher darin, ein paar Zeilen hinzuzufügen, um die App.config-Datei zu kopieren:

<Copy SourceFiles="$(OutDir)$(TargetFileName).config" DestinationFolder="$(WebProjectOutputDir)\bin" SkipUnchangedFiles="true" />

Es gibt viele Dinge in Microsoft.WebApplication.targets, die nur für Webanwendungen relevant sind und für andere Projekttypen entfernt werden können, aber ich lasse das dem Leser als Übung.

44
Mike Hadlow

TFS 2012+

Ich mag diese Lösung ...

Bearbeiten Sie Ihre Builddefinition. Setzen Sie im Abschnitt "Prozess" MSBuild arguments auf 

/p:GenerateProjectSpecificOutputFolder=true

So was:

enter image description here

35
Theo

Standardmäßig gibt jede Projektdatei (* .csproj, * .vbproj usw.) ein Standardausgabeverzeichnis an (normalerweise bin\Debug, bin\Release usw.). Team Build überschreibt dies tatsächlich, so dass Sie nicht nach Belieben entscheiden, welche Eigenschaften der Entwickler in der Projektdatei festlegt, sondern auch, dass Team Build Annahmen darüber treffen kann, wo sich die Ausgaben befinden.

Die einfachste Möglichkeit, dieses Verhalten zu überschreiben, besteht darin, CustomizableOutDir in der Elementgruppe "SolutionToBuild" wie folgt auf "true" zu setzen:

<ItemGroup>
  <SolutionToBuild Include="$(BuildProjectFolderPath)\path\MySolution.sln" />
    <Properties>CustomizableOutDir=true</Properties>
  </SolutionToBuild>
</ItemGroup>

Dadurch wird die Struktur des Ablageordners grob an das angepasst, was Sie beim Erstellen der Lösung lokal erhalten würden.

Diese Methode ist auf jeden Fall vorzuziehen, wenn Sie die Core * -Ziele außer Kraft setzen, was Upgrade-Probleme verursachen kann.

Setzen Sie für jeden SolutionToBuild-Knoten die Eigenschaft OutDir auf $ (OutDir)\SubFolder
Zum Beispiel:

  <ItemGroup>
   <SolutionToBuild Include="Project1.sln" >
    <Properties>OutDir=$(OutDir)\Project1\</Properties>      
   </SolutionToBuild>
   <SolutionToBuild Include="Project2.sln" >
    <Properties>OutDir=$(OutDir)\Project2\</Properties>      
   </SolutionToBuild>
   <SolutionToBuild Include="Project3.sln" >
    <Properties>OutDir=$(OutDir)\Project3\</Properties>      
   </SolutionToBuild>
  <ItemGroup>

(Dies funktioniert in TF2008, aber nicht in TF2005.)

6
user75810

Ich bin etwas spät dran bei der Beantwortung dieser Frage, aber es gibt eine sehr einfache Möglichkeit, die Antwort von Mike Hadlows zu implementieren. Jemand hat ein Nuget-Paket geschrieben, das genau das tut, worüber Mike spricht. Sie finden es hier: http://www.nuget.org/packages/PublishedApplications

5
CeejeeB

Update für TFS 2010 (und bevorstehendes TFS 2012). Jason Stangroome hat einen Nizza-Blog-Beitrag geschrieben, in dem er beschreibt, wie das geht.

http://blog.codeassassin.com/2012/02/03/override-the-tfs-team-build-outdir-property/

(Der obige Link ist tot ... Link zur zwischengespeicherten Version)

https://webcache.googleusercontent.com/search?q=cache:4rKu4oB3TwcJ:blog.stangroome.com/2012/02/03/override-the-tfs-team-build-outdir-property/+ & cd = 1 & hl = en & ct = clnk & gl = ca

Überschreiben Sie die TFS Team Build OutDir-Eigenschaft

Update: Mit .NET 4.5 gibt es einen einfacheren Weg .

Eine häufige Beschwerde von Benutzern des Buildsystems von Team Foundation Server ist, dass es die Ordnerstruktur der Projektausgaben ändert. Standardmäßig legt Visual Studio alle Dateien im jeweiligen Ordner/bin/oder/bin // des Projekts ab, Team Build verwendet jedoch nur eine flache Ordnerstruktur, in der alle Dateien im Stammverzeichnis des Ablageordners oder auch in einem Unterordner des Ablageordners abgelegt werden Ordner, in dem alle Projektausgaben gemischt sind.

Da Team Build dies durch Festlegen der OutDir-Eigenschaft über die MSBuild.exe-Befehlszeile in Kombination mit der MSBuild-Vorrangstellung erreicht, kann dieser Wert nicht einfach in MSBuild selbst und der gängigen Lösung geändert werden soll die Build Process Template * .xaml-Datei bearbeiten, um einen anderen Eigenschaftsnamen zu verwenden. Ich bevorzuge es jedoch, den Workflow nicht zu berühren, es sei denn, dies ist absolut notwendig.

Stattdessen verwende ich die Funktionen "Lösung vor Ziel" und "Inline-Aufgabe" von MSBuild v4, um die Standardimplementierung der MSBuild-Aufgabe zu überschreiben, mit der die einzelnen Projekte in der Lösung erstellt wurden. In meiner alternativen Implementierung verhindere ich, dass die OutDir-Eigenschaft übergeben wird, und übergebe stattdessen eine Eigenschaft namens PreferredOutDir, die bei Bedarf von einzelnen Projekten verwendet werden kann.

Der erste Teil, bei dem die Eigenschaft "OutDir" auf Lösungsebene durch die Eigenschaft "PreferredOutDir" ersetzt wird, besteht darin, dem Verzeichnis, in dem sich Ihre Lösungsdatei befindet, eine neue Datei hinzuzufügen. Diese neue Datei sollte nach dem Muster "before..sln.targets" benannt werden. ZB für eine Lösungsdatei mit dem Namen "Foo.sln" lautet die neue Datei "before.Foo.sln.targets". Der Inhalt dieser neuen Datei sollte so aussehen . Stellen Sie sicher, dass diese neue Datei in die Quellcodeverwaltung eingecheckt wird.

Der zweite Teil, mit dem jedes Projekt seine Ausgabeordnerstruktur steuern kann, besteht lediglich darin, der * .csproj- oder * .vbproj-Datei des Projekts eine Zeile hinzuzufügen (je nach Sprache). Suchen Sie das erste Element in der Projektdatei, für das kein Bedingungsattribut angegeben ist, und suchen Sie das entsprechende schließende Tag für dieses Element. Fügen Sie direkt über dem schließenden Tag eine Zeile wie die folgende hinzu:

<OutDir Condition=" '$(PreferredOutDir)' != '' ">$(PreferredOutDir)$(MSBuildProjectName)\</OutDir>

In diesem Beispiel wird das Projekt im Ablageordner von Team Build in einem Unterordner ausgegeben, der den gleichen Namen hat wie die Projektdatei (ohne die Erweiterung .csproj). Möglicherweise wählen Sie ein anderes Muster. Außerdem erstellen Webprojekte normalerweise einen eigenen Ausgabeordner unter einem Unterordner _PublishedWebSites des Ablageordners Team Build. Um dieses Verhalten beizubehalten, legen Sie einfach die OutDir-Eigenschaft so fest, dass sie genau der PreferredOutDir-Eigenschaft entspricht.

Sie können überprüfen, ob Ihre Änderungen auf Ihrem lokalen Computer wirksam waren, bevor Sie einchecken, indem Sie einfach MSBuild über die Befehlszeile ausführen und die OutDir-Eigenschaft wie Team Build angeben, z.

msbuild Foo.sln /p:OutDir=c:\TestDropFolder\

4
Jeremy Wiebe

Für diejenigen, die wissen wollen, wie das mit TFS 2010 funktioniert, hat dieser Beitrag mehrere Antworten, von denen der Link sehr gut für mich funktioniert.

1
Case

Sie könnten ein Buildscript für jedes Projekt haben, das genau das tut, was Sie möchten. Erstellen Sie einfach eine neue TFSBuild-Datei, fügen Sie die gewünschten Projekte der Elementgruppe hinzu (in der gewünschten Reihenfolge) und legen Sie die Stelle fest, an der Sie sie erstellen möchten möchte die Ausgabe sein. Dies geschieht durch Überschreiben der - Eigenschaft in Ihrer TFSBuild-Datei. 

Aber ich stimme auch dem vorherigen Poster zu. Warum laufen Sie nicht einfach mit einem einzigen Build-Skript und fügen am Ende eine Zip-Aufgabe hinzu? Wenn Sie ein Buildscript pro Projekt verwalten, wird der Wartungsaufwand erhöht.

0
Erling Paulsen

Sling dies in einer Propertygroup:

<CustomizableOutDir>true</CustomizableOutDir>

Dadurch wird die globale Eigenschaft 'CustomizableOutDir' überschrieben, die standardmäßig auf "False" gesetzt ist. Die Einstellung in den Eigenschaften von SolutionToBuild funktioniert nicht.

0
user386316