Share via


Exemplarische Vorgehensweise: Anpassen von Team Foundation Build mithilfe einer benutzerdefinierten Aufgabe

Aktualisiert: November 2007

Sie können Team Foundation Build erweitern, indem Sie eigene benutzerdefinierte Aufgaben erstellen und diese während eines Builds ausführen. In diesem Thema werden die Schritte erläutert, die zum Erweitern einer Builddefinition mit einer benutzerdefinierten Aufgabe erforderlich sind.

Erforderliche Berechtigungen

Zum Abschließen dieser exemplarischen Vorgehensweise muss die Build verwalten-Berechtigung auf Zulassen festgelegt sein. Weitere Informationen finden Sie unter Team Foundation Server-Berechtigungen.

Erstellen einer Builddefinition

Mit dem Dialogfeld Builddefinition können Sie eine neue Builddefinition erstellen. Sie können entweder eine vorhandene TFSBuild.proj-Datei verwenden oder mit dem MSBuild-Projektdateierstellungs-Assistenten eine neue Datei erstellen. Bearbeiten Sie die Datei TFSBuild.proj, um alle damit verknüpften Builddefinitionen anzupassen. Weitere Informationen zum Erstellen von Builddefinitionen finden Sie unter Gewusst wie: Erstellen einer Builddefinition.

Erstellen von benutzerdefinierten Aufgaben

Aufgaben stellen den Code bereit, der während des Buildprozesses ausgeführt wird. Diese Aufgaben sind in Target-Elementen von MSBuild-Projektdateien enthalten. MSBuild ist das Modul hinter Team Foundation Build. Benutzerdefinierte Aufgaben müssen ein MSBuild-kompatibles Format haben. Jede Aufgabe muss als .NET-Klasse implementiert werden, durch die die in der Assembly Microsoft.Build.Framework.dll definierte ITask-Schnittstelle eingerichtet wird.

Es gibt zwei Vorgehensweisen für das Implementieren einer Aufgabe:

  • Direktes Implementieren der ITask-Schnittstelle

  • Ableiten der Klasse von der Task-Hilfsklasse, die in der Assembly Microsoft.Build.Utilities.dll definiert ist. Task implementiert ITask und stellt Standardimplementierungen einiger ITask-Member bereit.

Bei beiden Ansätzen müssen Sie der Klasse eine Methode mit dem Namen Execute hinzufügen. Diese Methode wird aufgerufen, wenn die Aufgabe ausgeführt wird. Diese Methode übernimmt keine Parameter und gibt einen Boolean-Wert zurück: true bei erfolgreicher und false bei nicht erfolgreicher Ausführung der Aufgabe. Im folgenden Beispiel wird eine Aufgabe veranschaulicht, die keine Aktionen ausführt und true zurückgibt.

using System;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace MyTasks
{
    public class SimpleTask : Task
    {
        public override bool Execute()
        {
            return true;
        }
    }
}

Aufgaben können auch Parameter akzeptieren, Ereignisse auslösen und Ausgaben protokollieren. Weitere Informationen finden Sie unter MSBuild-Aufgaben und Übersicht über MSBuild.

Auschecken von TFSBuild.proj

Nachdem Sie die Aufgabe geschrieben haben, müssen Sie sie registrieren und in einem der Ziele aufrufen, damit der Aufgabencode am gewünschten Punkt im Buildvorgang ausgeführt wird. Wenn Sie mit dem MSBuild-Projektdateierstellungs-Assistenten eine MSBuild-Projektdatei erstellt und den Standardspeicherort in der Quellcodeverwaltung übernommen haben, befindet sich die Datei TFSBuild.proj im Ordner $/EigenesTeamprojekt/TeamBuildTypes/EigenerBuildname in der Visual Studio Team System-Quellcodeverwaltung. Bei diesem Szenario ist EigenesTeamprojekt der Name des Teamprojekts und der Stammknoten für alle Teamprojektquellen. EigenerBuildname steht für den Namen, den Sie der Builddefinition gegeben haben, für die die Datei TFSBuild.proj ursprünglich erstellt wurde.

Um den Quellcodeverwaltungsspeicherort der Datei TFSBuild.proj zu ermitteln, wählen Sie in Team Explorer im Ordner Builds die Builddefinition aus, klicken mit der rechten Maustaste darauf und klicken anschließend auf Bearbeiten. Der Quellcodeverwaltungsspeicherort der Datei TFSBuild.proj wird im Dialogfeld Builddefinition im Bereich Builddefinition angezeigt.

Hinweis:

Bearbeiten Sie nicht die Datei Microsoft.TeamFoundation.Build.targets, da die Anpassungen dann für alle Builds auf diesem Computer gelten.

Informationen über das Auschecken von Dateien finden Sie unter Arbeiten mit der Team Foundation-Versionskontrolle.

Registrieren der Aufgabe

Nachdem Sie die Aufgabe erstellt haben, müssen Sie diese registrieren, indem Sie sie in einem UsingTask-Element in der Datei TFSBuild.proj angeben. Das UsingTask-Element ordnet die Aufgabe der Assembly zu, die die Implementierung der Aufgabe enthält. Weitere Informationen finden Sie unter UsingTask-Element (MSBuild).

So registrieren Sie eine benutzerdefinierte Aufgabe

  1. Öffnen Sie die Datei TFSBuild.proj.

  2. Fügen Sie der Datei ein UsingTask-Element hinzu, und geben Sie die Details der Aufgabe an.

    Beispiel:

    <UsingTask 
        TaskName="MyTasks.SimpleTask" 
        AssemblyName="MyAssembly.Build.Tasks"/>
    

    – oder –

    <UsingTask 
        TaskName="MyTasks.SimpleTask" 
        AssemblyFile="MyAssembly.Build.Tasks.dll"/>
    

    – oder –

    <UsingTask
        TaskName="MyTasks.SimpleTask"
        AssemblyFile="c:\somediskpath\MyAssembly.Build.Tasks.dll"/>
    
  3. Speichern Sie die Datei.

Ausführen der benutzerdefinierten Aufgabe

Nach dem Erstellen und Registrieren der Aufgabe müssen Sie den Punkt im Buildprozess angeben, zu dem die Aufgabe ausgeführt werden soll.

So führen Sie eine Aufgabe aus

  1. Legen Sie fest, wo im Buildprozess die benutzerdefinierte Aufgabe ausgeführt werden soll.

    Weitere Informationen zum Erweitern des Buildprozesses finden Sie unter Team Foundation Build-Konfigurationsdateien.

  2. Öffnen Sie TFSBuild.proj, und fügen Sie das Target-Element hinzu, das Sie oben ausgewählt haben.

  3. Fügen Sie das Aufgabenelement hinzu, um die Aufgabe im Target-Element auszuführen.

    Beispielsweise wird mit dem folgenden XML-Code in TFSBuild.proj die SimpleTask-Aufgabe im BeforeGet-Ziel ausgeführt, das direkt vor dem Get-Ziel ausgeführt wird.

    <Target Name="BeforeGet">
        <SimpleTask />
    </Target>
    
  4. Speichern Sie die Datei.

Einchecken der Dateien

Sie müssen die Datei TFSBuild.proj einchecken, damit die Änderungen wirksam werden. Team Foundation Build kopiert diese Datei aus der Quellcodeverwaltung auf den Buildcomputer, sodass sich die an der lokalen Kopie vorgenommenen Änderungen nicht auf den Build auswirken. Weitere Informationen zum Einchecken von Dateien in die Quellcodeverwaltung finden Sie unter Gewusst wie: Einchecken von ausstehenden Änderungen.

Wenn Sie möchten, dass Team Foundation Build die DLL der Aufgabe auf den Buildcomputer kopiert, müssen Sie die DLL unter dem Teamprojektknoten der Quellcodeverwaltung hinzufügen.

Beispielaufgabe

Bei diesem Beispiel wird eine benutzerdefinierte Aufgabe erstellt, die die mit der Datei TFSBuild.proj verknüpften Builddefinitionen erweitert, indem die Größe der durch den Build erstellten Dateien protokolliert wird. Das Beispiel besteht aus zwei Teilen:

  • Aufgabencode

  • Die Datei TFSBuild.proj.

Die protokollierten Informationen dieser Aufgabe können in der Buildprotokolldatei Buildlog.txt im Buildablageordner eingesehen werden. Das Buildprotokoll enthält z. B. Informationen ähnlich den Folgenden:

Die Gesamtgröße im Verzeichnis d:\BuildDir\MyTeamProj\MyBuildType\sources\..\Binaries\Release beträgt 9216 Bytes.

C#-Aufgabencode

Das untenstehende Beispiel enthält den Code, mit dem die Gesamtgröße aller Binärdateien durch Summieren der Größe der Dateien im Ordner Binaries berechnet wird.

Hinweis:

Alle während eines Builds generierten Binärdateien befinden sich im Ordner Binaries auf dem Build-Agenten.

Damit diese Aufgabe in einem Build verwendet werden kann, muss die kompilierte DLL unter dem Teamprojektordner in die Quellcodeverwaltung eingecheckt werden. Dies garantiert, dass die Datei während eines Builds auf den Build-Agenten kopiert wird.

Mit dem folgenden Code wird die Größe der Binärdateien im Ordner Binaries des Buildverzeichnisses berechnet. Die Projektmappenstammeigenschaft wird vom Team Foundation Build-Skript an diese Aufgabe übergeben.

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Build.Framework; 
using Microsoft.Build.Utilities;
using System.Diagnostics;
using System.IO;

namespace BuildTask
{
    public class BinSize : Task
    {
        private string sourceDir;

        [Required]
        public string SourceDir
        {
            get { return sourceDir; }
            set { sourceDir = value; }
        }
        public override bool Execute()
        {
            string szDir = sourceDir + "\\..\\Binaries";
            ProcessDirectory(szDir);
            return true;
        }
        private void ProcessDirectory(string targetDirectory)
        {
            // Process the list of files found in the directory.
            string[] fileEntries = Directory.GetFiles(targetDirectory, "*.*");
            if (fileEntries.Length > 0)
            {
                dwSize = 0;
                szCurrDir = targetDirectory;
                foreach (string fileName in fileEntries)
                    ProcessFile(fileName);
                ////////////////////////////////////////////////////////////////////////
                // This log message would just print out a line in the build log file. 
                // You need to add code to do what you need to do with this data. e.g. 
                // publishing it into the warehouse for reporting. 
                ///////////////////////////////////////////////////////////////////////
                Log.LogMessage("The total size of is {0} bytes in {1} dir",
                    dwSize, targetDirectory);
            }
            // Recurse into subdirectories of this directory.
            string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
            foreach (string subdirectory in subdirectoryEntries)
                ProcessDirectory(subdirectory);
        }
        private void ProcessFile(string path)
        {
            FileInfo fi = new FileInfo(path);
            dwSize = dwSize + fi.Length;
        }
        private long dwSize;
        private string szCurrDir;
    }
}

Datei TFSBuild.proj

Nachdem die Aufgabe kompiliert und in die Quellcodeverwaltung eingecheckt wurde, muss sie aus der Datei TFSBuild.proj aufgerufen werden. In diesem Beispiel sollte die Aufgabe aufgerufen werden, nachdem alle Dateien kompiliert und alle Binärdateien in das Verzeichnis Binaries kopiert wurden. Daher sollte die Aufgabe im BeforeDropBuild-Ziel ausgeführt werden. Weitere Informationen zu den erweiterbaren Zielen in TFSBuild.proj finden Sie unter Team Foundation Build-Konfigurationsdateien.

Das folgende Beispiel enthält den Code in der geänderten Datei TFSBuild.proj. Der XML-Code in diesem Beispiel wurde fast vollständig vom MSBuild-Projektdateierstellungs-Assistent generiert, mit Ausnahme des UsingTask-Elements und des Target-Elements, die sich am Ende der Datei befinden.

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="DesktopBuild" xmlns="https://schemas.microsoft.com/developer/msbuild/2003">
  <!-- TO EDIT BUILD TYPE DEFINITION

   TODO: Update all of the comments in this file!

   To edit the build type, you will need to edit this file which was generated
   by the Create New Build Type wizard.  This file is under source control and
   needs to be checked out before making any changes.

   The file is available at:
   
       $/{TeamProjectName}/TeamBuildTypes/{BuildTypeName}
       
   where you will need to replace TeamProjectName and BuildTypeName with your
   Team Project and Build Type name that you created

   Checkout the file
     1. Open Source Control Explorer by selecting View -> Other Windows -> Source Control Explorer
     2. Ensure that your current workspace has a mapping for the $/{TeamProjectName}/TeamBuildTypes folder and 
        that you have done a "Get Latest Version" on that folder
     3. Browse through the folders to {TeamProjectName}->TeamBuildTypes->{BuildTypeName} folder
     4. From the list of files available in this folder, right click on TfsBuild.Proj. Select 'Check Out For Edit...'


   Make the required changes to the file and save

   Checkin the file
     1. Right click on the TfsBuild.Proj file selected in Step 3 above and select 'Checkin Pending Changes'
     2. Use the pending checkin dialog to save your changes to the source control

   Once the file is checked in with the modifications, all future builds using
   this build type will use the modified settings
  -->

  <!-- Do not edit this -->
  <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />

  <ProjectExtensions>

    <!-- Team Foundation Build Version - DO NOT CHANGE -->
    <ProjectFileVersion>2</ProjectFileVersion>

    <!--  DESCRIPTION
     TODO: Obsolete.
    -->
    <Description>this one automatically  builds on check in</Description>

    <!--  BUILD MACHINE
     TODO: Obsolete.
    -->
    <BuildMachine>ahetod-test2</BuildMachine>

  </ProjectExtensions>

  <PropertyGroup>

    <!-- Properties set by the build type creation wizard -->
    
    <!--  TEAM PROJECT
     TODO: Obsolete.
    -->
    <TeamProject>TeamProjectName</TeamProject>

    <!--  BUILD DIRECTORY
     TODO: Obsolete.
    -->
    <BuildDirectoryPath>C:\Documents and Settings\user\Local Settings\Temp\1\TeamProjectName\BuildDefinitionName</BuildDirectoryPath>

    <!--  DROP LOCATION
     TODO: Obsolete.
    -->
    <DropLocation>\\UNKNOWN\drops</DropLocation>

    <!--  TESTING
     Set this flag to enable/disable running tests as a post build step.
    -->
    <RunTest>false</RunTest>

    <!--  CODE ANALYSIS
     To change CodeAnalysis behavior edit this value. Valid values for this
     can be Default,Always or Never.

         Default - To perform code analysis as per the individual project settings
         Always  - To always perform code analysis irrespective of project settings
         Never   - To never perform code analysis irrespective of project settings
     -->
    <RunCodeAnalysis>Never</RunCodeAnalysis>

    <!-- Additional Properties -->

    <!--  WorkItemType
     The type of the work item created on a build break - if empty, "Bug" will be used 
     -->
    <WorkItemType Condition=" '$(WorkItemType)'=='' "></WorkItemType>

    <!--  WorkItemFieldValues
     Add/edit key value pairs to set values for fields in the work item created
     during the build process. Please make sure the field names are valid 
     for the work item type being used.
     -->
    <WorkItemFieldValues>Symptom=build break;Steps To Reproduce=Start the build using Team Build</WorkItemFieldValues>

    <!--  WorkItemTitle
     Title for the work item created on build failure 
     -->
    <WorkItemTitle>Build failure in build:</WorkItemTitle>

    <!--  DescriptionText
     Description for the work item created on a build failure 
     -->
    <DescriptionText>This work item was created by Team Build on a build failure.</DescriptionText>

    <!--  BuildLogText
     Additional text for the work item create on a build failure.
     -->
    <BuildlogText>The build log file is at:</BuildlogText>

    <!--  ErrorWarningLogText
     Additional text for the work item create on a build failure 
     -->
    <ErrorWarningLogText>The errors/warnings log file is at:</ErrorWarningLogText>

    <!--  UpdateAssociatedWorkItems
     Set this flag to enable/disable updating associated workitems on a successful build
     -->
    <UpdateAssociatedWorkItems>true</UpdateAssociatedWorkItems>

    <!--  AdditionalVCOverrides
     Additional text for the VCOverrides file generated for VC++ projects
     -->
    <AdditionalVCOverrides></AdditionalVCOverrides>

    <!--  CustomPropertiesForClean
     Custom properties to pass to the MSBuild task while calling the "Clean" target for all solutions.
     The format should be: PropertyName1=value1;PropertyName2=value2;...
     -->
    <CustomPropertiesForClean></CustomPropertiesForClean>

    <!--  CustomPropertiesForBuild
     Custom properties to pass to the MSBuild task while calling the default targets for all solutions.
     The format should be: PropertyName1=value1;PropertyName2=value2;...  To pass custom properties to
     individual solutions, use the Properties metadata item of the SolutionToBuild ItemGroup.
     -->
    <CustomPropertiesForBuild></CustomPropertiesForBuild>

  </PropertyGroup>

  <ItemGroup>
    <!--  SOLUTIONS
     The paths of the solutions to build. To add/delete solutions, edit this
     ItemGroup. For example, to add a solution MySolution.sln, add the following line:
         
         <SolutionToBuild Include="$(BuildProjectFolderPath)\path\MySolution.sln" />

     To change the order in which the solutions are built, modify the order in
     which the solutions appear below.
     
     To call a target (or targets) other than the default, add a metadata item named
     Targets.  To pass custom properties to the solution, add a metadata item named
     Properties.  For example, to call the targets MyCustomTarget1 and MyCustomTarget2,
     passing in properties Property1 and Property2, add the following:
         
         <SolutionToBuild Include="$(BuildProjectFolderPath)\path\MySolution.sln">
             <Targets>MyCustomTarget1;MyCustomTarget2</Targets>
             <Properties>Property1=Value1;PropertyTwo=Value2</Properties>
         </SolutionToBuild>
    -->
    <SolutionToBuild Include="$(BuildProjectFolderPath)/../../SimpleAppToBuild/SimpleAppToBuild.sln">
        <Targets></Targets>
        <Properties></Properties>
    </SolutionToBuild>

  </ItemGroup>

  <ItemGroup>
    <!--  CONFIGURATIONS
     The list of configurations to build. To add/delete configurations, edit
     this value. For example, to add a new configuration, add the following lines:
         
         <ConfigurationToBuild Include="Debug|x86">
             <FlavorToBuild>Debug</FlavorToBuild>
             <PlatformToBuild>x86</PlatformToBuild>
         </ConfigurationToBuild>

     The Include attribute value should be unique for each ConfigurationToBuild node.
    -->
    <ConfigurationToBuild Include="Release|Any CPU">
        <FlavorToBuild>Release</FlavorToBuild>
        <PlatformToBuild>Any CPU</PlatformToBuild>
    </ConfigurationToBuild>

  </ItemGroup>

  <ItemGroup>
    <!--  TEST ARGUMENTS
     If the RunTest property is set to true then the following test arguments will be used to run 
     tests. Tests can be run by specifying one or more test lists and/or one or more test containers.

     To run tests using test lists, add MetaDataFile items and associated TestLists here:
     
        <MetaDataFile Include="$(SolutionRoot)\HelloWorld\HelloWorld.vsmdi">
            <TestList>BVT1;BVT2</TestList>
        </MetaDataFile>

     To run tests using test containers, add TestContainer items here:
     
        <TestContainer Include="$(OutDir)\HelloWorldTests.dll" />
        <TestContainer Include="$(SolutionRoot)\TestProject\WebTest1.webtest" />
        <TestContainer Include="$(SolutionRoot)\TestProject\LoadTest1.loadtest" />

    -->

  </ItemGroup>

  <ItemGroup>
    <!--  ADDITIONAL REFERENCE PATH
     The list of additional reference paths to use while resolving references.
     For example:
     
         <AdditionalReferencePath Include="C:\MyFolder\" />
         <AdditionalReferencePath Include="C:\MyFolder2\" />
    -->
  </ItemGroup> 
 <UsingTask TaskName="BuildTask.BinSize" AssemblyFile="$(SolutionRoot)\tools\BuildTask.dll" />  <Target Name="BeforeDropBuild">    <BinSize SourceDir="$(SolutionRoot)" />  </Target>
  
</Project>

Siehe auch

Aufgaben

Gewusst wie: Schreiben von Aufgaben

Konzepte

MSBuild

Weitere Ressourcen

Anpassen von Team Foundation Build