MSBuild 4.0 New Features: Inline Tasks

 

Mit dem Release des .NET Frameworks 4.0 wird auch MSBuild 4.0 erscheinen, wie alle Bestandteile des Frameworks, wird auch MSBuild um einige nette Features erweitert.

Eines der interessantesten Features sind wohl Inline Tasks, bis Dato muss man eine Klasse vom Interface ITask ableiten um einen eigenen Task für MSBuild zu realisieren. Dies bringt unter anderem wieder den Nachteil mit sich, dass man die Assembly, welche den Task beinhaltet mit ausrollen muss, damit das Buildscript auf fremden Systemen ausgeführt werden kann.

In MSBuild 4.0 gibt es nun die Möglichkeit Tasks direkt im Buildscript zu erstellen, dadurch entfällt der Deploymentaufwand und die Erstellung von Buildfiles wird zunehmend agiler.

Definition eines InlineTasks

Im aktuelle Relese Candidate von Visual Studio ist leider noch kein aktuelles Schema für MSBuild vorhanden, welches auch IntelliSense für die Changes von MSBuild 4.0 ermöglicht, daher muss das Project Node wie gehabt definiert werden.

Einzig die ToolsVersion muss jetzt auf 4.0 gesetzt werden, damit die Buildscripts auch gegen die Implementierung von MSBuild 4.0 laufen.

 

<Project xmlns="http://schema.microsoft.com/developer/msbuild/2003"
  ToolsVersion="4.0">
   <!-- ... -->
</Project>

Definiert werden InlineTasks über das XML-Element UsingTask direkt unterhalb des Project Nodes.

Das UsingTask Node bietet in der Version 4.0 einige neue Attribute und Subnodes, die in den Vorgängerversionen nicht enthalten sind.

 

Attribute von UsingTask

Das UsingTask Node verfügt über die folgenden Attribute

  • TaskFactory
    • Pflicht-Attribut
    • Implementierungvon ITaskFactory, welche den InlineTask ausführt
    • CodeTaskFactory und XamlTaskFactory werden mit Microsoft.Build.Tasks.v4.0.dll ausgeliefert
  • TaskName
    • Pflicht Attribut
    • Name des InlineTasks
    • Wird zur späteren Referenzierung verwendet
  • AssemblyFile
    • Pflicht Attribut, wenn AssemblyName nicht angegeben
    • Assembly, welche die TaskFactory beinhaltet
    • $(MSBuildToolsPath)\Microsoft.BuildTasks.v4.0.dll für CodeTaskFactory oder XamlTaskFactory
  • AssemblyName
    • Pflicht Attribut, wenn AssemblyFile nicht angegeben
    • FQN der Assembly aus dem GAC

SubNodes von UsingTask

Neben den Attributen verfügt UsingTask auch über SubNodes, die verwendet werden um InlineTasks zu definieren.

  • ParameterGroup
    • Optional
    • Wird verwendet um spezifische Properties zu definieren
  • Task
    • Pflicht
    • Beschreibt den InlineTask

Das Task-Node

Bis zu dieser Stelle wurden erst einige MetaDaten des InlineTasks definiert, um die Definition zu vervollständigen, verfügt der Task-Node über weitere SubNodes, die angegeben werden müssen / können.

  • Reference
    • Optional
    • Wird verwendet um Assemblyverweise, die nicht durch das Buildfile bereits eingefügt wurden hinzuzufügen.
  • Using
    • Optional
    • Wird verwendet um Namespaces einzubinden, die nicht bereits durch das Buildfile eingefügt wurden.
  • Code
    • Pflicht für InlineTasks
    • Definiert den InlineTask

 

Das Code-Node

Das Code Node verfügt über die Attribute

  • Type
    • Pflicht
    • Gibt an, welche Art der InlineTask haben soll
      • Class
        • Das Code Node beschreibt eine gesamte, von ITask abgeleitete Klasse
      • Method
        • Das Code Node beschreibt lediglich die Methode Execute
      • Fragment
        • Das Code Node beinhaltet lediglich ein Fragment innerhalb der Execute Methode
          • Keine Methoden-Signatur
          • Kein Rückgabewert
  • Language
    • Pflicht
    • Gibt an, in welcher Sprache der InlineTask geschrieben ist
      • cs – C#
      • vb – Visual Basic

Neben diesen Attribute benötigt das Code Node noch ein Child Element, nämlich den eigentlichen Code in Form eines CDATA Nodes.

 

Ein einfaches Beispiel

Das einfachste Beispiel für einen InlineTask ist eine simple Konsolenausgabe, die mit nur wenigen Zeilen XML definiert ist.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" 
   ToolsVersion="4.0"> 
   <UsingTask TaskFactory="CodeTaskFactory" 
      TaskName="MyConsoleTask" 
      AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> 
      <ParameterGroup/> 
      <Task> 
        <Using Namespace="System"/> 
        <Code Type="Fragment" Language="cs"> 
           <![CDATA[
               Console.WriteLine("This is just a test");
           ]]> 
        </Code> 
     </Task> 
   </UsingTask> 
   <Target Name="MyInlineTarget"> 
      <MyConsoleTask/> 
    </Target> 
</Project>

Führt man das Buildskript mit dem Befehl

MSBuild.exe MyInlineTask.csproj /t:MyInlineTarget

aus, ergibt sich die folgende Ausgabe

msbuild4inlinetasks1

Einfach, schnell, agil, lose Kopplung! Das ist der Ziel von InlineTasks in MSBuild 4.0.  Das hier gezeigte Buildscript ist auf jedem! Rechner der über MSBuild 4.0 verfügt lauffähig, es wird keine weitere DLL benötigt, einfach das Script ausführen und alle InlineTasks funktionieren.

Lediglich die Testbarkeit des Codes ist nicht gegeben! – Schade, also keine UnitTest, kein CompileTimeCheck! Also Achtung!

 

Ein etwas praktischeres Beispiel

Ok, der erste InlineTask ist geschrieben, aber bringt der etwas?? Nein eigentlich nicht.. Ein Szenario was öfters auftritt, ist das Dateien jeglicher Art durch den Buildvorgang verschoben werden sollen.

Hierfür gibt es OOB in MSBuild keinen Task, oftmals behilft man sich einer Kompositions von Copy- und Delete-Tasks oder greift auf die MSBuild Community Tasks zurück.

Der Weg über Verkettung von Copy- und DeleteTask ist gangbar, allerdings nicht besonders hübsch. Der Weg über die CommunityTasks bedarf dem Deployment der entsprechenden Assemblies und Target-Files.

Durch einen einfachen InlineTask, sind all diese Nachteile vom Tisch

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
   ToolsVersion="4.0"> 
  <ItemGroup> 
   <TextFiles Include="**\*.txt"/> 
  </ItemGroup> 
  <UsingTask TaskFactory="CodeTaskFactory" 
    TaskName="MoveTask" 
    AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"> 
     <ParameterGroup> 
      <FilesToMove Required="TRUE" ParameterType="Microsoft.Build.Framework.ITaskItem[]"/> 
      <TargetDirectory Required="TRUE" ParameterType="System.String"/> 
     </ParameterGroup> 
     <Task> 
      <Using Namespace="System.IO"/> 
      <Code Type="Fragment" Language="cs"> 
       <![CDATA[
        for(int i=0; i<FilesToMove.Length; i++ ) 
        {
         File.Move(FilesToMoveIdea.GetMetadata("FullPath"), 
           Path.Combine(TargetDirectory,
           String.Format("{0}{1}",
             FilesToMoveIdea.GetMetadata("FileName"), 
             FilesToMoveIdea.GetMetadata("Extension")
          )));
        } 
       ]]> 
     </Code> 
    </Task> 
  </UsingTask> 
  <Target Name="MyTest"> 
   <MoveTask FilesToMove="@(TextFiles)" TargetDirectory="C:"/> 
  </Target> 
</Project>

Was ist neu hier? Nun neben der Tatsache, dass der Namespace System.IO in dem InlineTask verwendet wird, werden nun auch Parameter für den InlineTask definiert.

Parameter für InlineTasks

Damit InlineTasks in der Praxis Verwendung finden können, musste es Ihnen ermöglicht werden Parameter zu verwalten. Über das Node ParameterGroup kann man hierbei In- und Output Parameter definieren, die im InlineTask dann als Properties zur Verfügung stehen.

Genau wie bei Standard-MSBuild-Properties, definiert auch hier der Identifier des Nodes den Namen der Property. Jede Property kann über die folgenden Attribute verfügen

  • Required
    • Gibt an ob der Parameter bei der Verwendung des Tasks angegeben werden muss.
    • Optional
    • Defaultvalue: false
  • ParameterType
    • Definiert den Typen des Parameters
    • Optional
    • Defaultvalue: System.String
  • Output
    • Gibt an ob dieser Parameter ein Output-Parameter ist
    • Optional
    • Defaultvalue: false

Fazit

InlineTasks sind eine der wichtigsten Neuerungen in MSBuild 4.0. Mit der Hilfe von InlineTasks kann man schnell und agil neue Buildscripte erstellen und auf den unterschiedlichsten Systemen, sofern das .NET Framework 4.0 installiert ist, einsetzen.

 

Technorati-Tags: ,
DotNetKicks-DE Image
Published Montag, 1. März 2010 23:44 von ThorstenHans
Abgelegt unter: , ,

Kommentare

# MSBuild 4.0 New Features: BeforeTargets and AfterTargets

Dienstag, 2. März 2010 11:59 von .NET rocks

Neben den bereits vorgestellten Neuerungen Inline Tasks Property Functions sind auch BeforeTargets und

# Das MSBuild Universum - .NET rocks

Mittwoch, 17. März 2010 11:26 von Das MSBuild Universum - .NET rocks

Ping Antwort von  Das MSBuild Universum - .NET rocks

# MSBuild 4.0 Inline Tasks

Montag, 5. April 2010 23:46 von dotnet-kicks.de

Sie wurden gekickt (eine gute Sache) - Trackback von dotnet-kicks.de

# re: MSBuild 4.0 New Features: Inline Tasks

Mittwoch, 15. Juni 2011 11:43 von Lars Corneliussen

> In MSBuild 4.0 gibt es nun die Möglichkeit Tasks direkt im Buildscript

> zu erstellen, dadurch entfällt der Deploymentaufwand und die Erstellung

> von Buildfiles wird zunehmend agiler.

Wenn es danach ginge... Die Stärke von MSBuild, Nant, Ant & Co. ist ja gerade, dass dinge deklarativ sein sollen. Statt der generischen Auswege sollte MS wenn schon lieber eine vernünftige Integration für IronRuby/Python oder PowerShell schaffen... Die sind wenigstens für "dynamic" geschaffen...

Aber klar. Erstmal wirkt es wie ein nettes Feature.

Kommentar abgeben

(verpflichtend) 
(verpflichtend) 
(optional)
(verpflichtend)