Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
MSBuild-Aufgaben werden in der Regel durch Kompilieren einer Klasse erstellt, die die ITask Schnittstelle implementiert. Weitere Informationen finden Sie unter Aufgaben.
Wenn Sie den Aufwand für die Erstellung eines kompilierten Vorgangs vermeiden möchten, können Sie einen Vorgang inline in der Projektdatei oder in einer importierten Datei erstellen. Sie müssen keine separate Assembly erstellen, um die Aufgabe zu hosten. Die Verwendung einer Inlineaufgabe erleichtert das Nachverfolgen des Quellcodes und die Bereitstellung der Aufgabe. Der Quellcode ist in die MSBuild-Projektdatei oder importierte Datei integriert, in der Regel eine .targets Datei.
Sie erstellen eine Inline-Aufgabe mithilfe einer Codeaufgabenfabrik. Achten Sie bei der aktuellen Entwicklung darauf, RoslynCodeTaskFactory zu verwenden, nicht CodeTaskFactory.
CodeTaskFactory unterstützt nur C#-Versionen bis zu 4.0.
Inlineaufgaben sind als Komfort für kleine Vorgänge gedacht, die keine komplizierten Abhängigkeiten erfordern. Die Debuggingunterstützung für Inlineaufgaben ist begrenzt. Es wird empfohlen, eine kompilierte Aufgabe anstelle einer Inlineaufgabe zu erstellen, wenn Sie komplexeren Code schreiben möchten, auf ein NuGet-Paket verweisen, externe Tools ausführen oder Vorgänge ausführen, die Fehlerbedingungen erzeugen könnten. Außerdem werden Inlineaufgaben jedes Mal kompiliert, wenn Sie ein Build durchführen, was sich spürbar auf die Buildleistung auswirken kann.
Die Struktur einer Inline-Aufgabe
Eine Inlineaufgabe ist in einem UsingTask-Element enthalten. Die Inlineaufgabe und das UsingTask darin enthaltene Element sind in der Regel in einer .targets Datei enthalten und bei Bedarf in andere Projektdateien importiert. Hier ist eine einfache Inlineaufgabe, die nichts tut, aber die Syntax veranschaulicht:
<!-- This simple inline task does nothing. -->
<UsingTask
TaskName="DoNothing"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Reference Include="" />
<Using Namespace="" />
<Code Type="Fragment" Language="cs">
</Code>
</Task>
</UsingTask>
Das UsingTask-Element im Beispiel verfügt über drei Attribute, die die Aufgabe und die Inline-Aufgabenfabrik beschreiben, durch die sie kompiliert wird.
Das
TaskNameAttribut benennt die Aufgabe in diesem FallDoNothing.Das
TaskFactoryAttribut benennt die Klasse, die die Inline-Task-Fabrik implementiert.Das
AssemblyFileAttribut gibt den Speicherort der Inline-Task-Factory an. Alternativ können Sie dasAssemblyName-Attribut verwenden, um den vollqualifizierten Namen der Inline-Task-Factory-Klasse anzugeben, die sich typischerweise in$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dllbefindet.
Die verbleibenden Elemente des DoNothing Vorgangs sind leer und werden bereitgestellt, um die Reihenfolge und Struktur eines Inlinevorgangs zu veranschaulichen. Ein vollständiges Beispiel wird weiter unten in diesem Artikel vorgestellt.
Das
ParameterGroup-Element ist optional. Wenn angegeben, deklariert sie die Parameter für den Vorgang. Weitere Informationen zu Eingabe- und Ausgabeparametern finden Sie weiter unten in diesem Artikel unter Eingabe- und Ausgabeparameter .Das
TaskElement beschreibt und enthält den Quellcode der Aufgabe.Das
ReferenceElement gibt Verweise auf die .NET-Assemblys an, die Sie in Ihrem Code verwenden. Die Verwendung dieses Elements entspricht dem Hinzufügen eines Verweises auf ein Projekt in Visual Studio. DasIncludeAttribut gibt den Pfad der Assembly an, auf die verwiesen wird. Assemblys in mscorlib, .NET Standard, Microsoft.Build.Framework und Microsoft.Build.Utilities.Core sowie einige Assemblys, auf die transitiv als Abhängigkeiten verwiesen wird, sind ohneReferenceverfügbar.Das
UsingElement listet die Namespaces auf, auf die Sie zugreifen möchten. Dieses Element entspricht derusingDirektive in C#. DasNamespaceAttribut gibt den einzuschließden Namespace an. Es funktioniert nicht, eineusingDirektive in den Inlinecode einzufügen, da dieser Code in einen Methodentext eingefügt wird, in demusingDirektiven nicht zulässig sind.
Reference und Using Elemente sind sprachunabhängig. Inlineaufgaben können in Visual Basic oder C# geschrieben werden.
Hinweis
Elemente, die vom Task-Element enthalten werden, sind spezifisch für die Task-Factory, in diesem Fall die Code-Task-Factory.
Code-Element
Das letzte untergeordnete Element, das innerhalb des Task Elements angezeigt werden soll, ist das Code Element. Das Code Element enthält oder sucht den Code, den Sie in einer Aufgabe kompilieren möchten. Was Sie in das Code Element einfügen, hängt davon ab, wie Sie die Aufgabe schreiben möchten.
Das Language Attribut gibt die Sprache an, in der Ihr Code geschrieben wird. Zulässige Werte sind cs für C# vb für Visual Basic.
Das Type-Attribut gibt den Codetyp an, der im Code-Element vorliegt.
Wenn der Wert lautet
TypeClass, enthält dasCodeElement Code für eine Klasse, die von der ITask Schnittstelle abgeleitet wird.Wenn der Wert
TypelautetMethod, definiert der Code eine Außerkraftsetzung derExecuteMethode der ITask Schnittstelle.Wenn der Wert von
TypeistFragment, definiert der Code den Inhalt derExecuteMethode, aber nicht die Signatur oder diereturnAnweisung.
Der Code selbst wird in der Regel zwischen einer <![CDATA[ Markierung und einer ]]> Markierung angezeigt. Da sich der Code in einem CDATA-Abschnitt befindet, müssen Sie sich keine Gedanken darüber machen, reservierte Zeichen zu entfernen, z. B. "<" oder ">".
Alternativ können Sie das Source Attribut des Code Elements verwenden, um den Speicherort einer Datei anzugeben, die den Code für ihre Aufgabe enthält. Der Code in der Quelldatei muss vom Typ sein, der durch das Type Attribut angegeben wird. Wenn das Source Attribut vorhanden ist, ist der Standardwert von TypeClass. Wenn Source nicht vorhanden, lautet Fragmentder Standardwert .
Hinweis
Beim Definieren der Aufgabenklasse in der Quelldatei muss der Klassenname dem TaskName Attribut des entsprechenden UsingTask-Elements zustimmen.
HelloWorld
Hier ist ein Beispiel für eine einfache Inlineaufgabe. Die HelloWorld-Aufgabe zeigt "Hello, world!" auf dem Standardmäßigen Fehlerprotokollierungsgerät an, das in der Regel die Systemkonsole oder das Visual Studio-Ausgabefenster ist.
<Project>
<!-- This simple inline task displays "Hello, world!" -->
<UsingTask
TaskName="HelloWorld"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll" >
<ParameterGroup />
<Task>
<Using Namespace="System"/>
<Using Namespace="System.IO"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
// Display "Hello, world!"
Log.LogError("Hello, world!");
]]>
</Code>
</Task>
</UsingTask>
</Project>
Sie können den Vorgang "HelloWorld" in einer Datei speichern, die " HelloWorld.targets" heißt, und sie dann wie folgt aus einem Projekt aufrufen.
<Project>
<Import Project="HelloWorld.targets" />
<Target Name="Hello">
<HelloWorld />
</Target>
</Project>
Eingabe- und Ausgabeparameter
Inline-Aufgabenparameter sind untergeordnete Elemente eines ParameterGroup-Elements. Jeder Parameter verwendet den Namen des Elements, das es definiert. Der folgende Code definiert den Parameter Text.
<ParameterGroup>
<Text />
</ParameterGroup>
Parameter können mindestens eins dieser Attribute aufweisen:
-
Requiredist ein optionales Attribut, das standardmäßig istfalse. Wenntrue, dann ist der Parameter erforderlich und muss vor dem Aufrufen der Aufgabe einen Wert erhalten. -
ParameterTypeist ein optionales Attribut, das standardmäßig istSystem.String. Er kann auf jeden vollqualifizierten Typ festgelegt werden, der entweder ein Element oder ein Wert ist, der mithilfe einer ChangeTypeZeichenfolge in und aus einer Zeichenfolge konvertiert werden kann. (Mit anderen Worten, jeder Typ, der an und von einer externen Aufgabe übergeben werden kann.) -
Outputist ein optionales Attribut, das standardmäßig istfalse. Fallstrue, muss dem Parameter ein Wert zugewiesen werden, bevor von der Execute-Methode zurückgekehrt wird.
Beispiel:
<ParameterGroup>
<Expression Required="true" />
<Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<Tally ParameterType="System.Int32" Output="true" />
</ParameterGroup>
definiert die folgenden drei Parameter:
Expressionist ein erforderlicher Eingabeparameter vom Typ "System.String".Filesist ein erforderlicher Eingabeparameter für Elementlisten.Tallyist ein Ausgabeparameter vom Typ "System.Int32".
Wenn das Code-Element das Type-Attribut von Fragment oder Method hat, werden Eigenschaften automatisch für jeden Parameter erstellt. Andernfalls müssen Eigenschaften explizit im Aufgabenquellcode deklariert werden und müssen exakt mit ihren Parameterdefinitionen übereinstimmen.
Debuggen einer Inlineaufgabe
MSBuild generiert eine Quelldatei für die Inlineaufgabe und schreibt die Ausgabe in die Textdatei mit einem GUID-Dateinamen im Ordner "Temporäre Dateien", "AppData\Local\Temp\MSBuildTemp". Die Ausgabe wird normalerweise gelöscht, aber um diese Ausgabedatei beizubehalten, können Sie die Umgebungsvariable MSBUILDLOGCODETASKFACTORYOUTPUT auf 1 festlegen.
Beispiel 1
Die folgende Inlineaufgabe ersetzt jedes Vorkommen eines Tokens in der angegebenen Datei durch den angegebenen Wert.
<Project>
<UsingTask TaskName="TokenReplace" TaskFactory="RoslynCodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll">
<ParameterGroup>
<Path ParameterType="System.String" Required="true" />
<Token ParameterType="System.String" Required="true" />
<Replacement ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs"><![CDATA[
string content = File.ReadAllText(Path);
content = content.Replace(Token, Replacement);
File.WriteAllText(Path, content);
]]></Code>
</Task>
</UsingTask>
<Target Name='Demo' >
<TokenReplace Path="Target.config" Token="$MyToken$" Replacement="MyValue"/>
</Target>
</Project>
Beispiel 2
Die folgende Inline-Aufgabe generiert eine Serienausgabe. Dieses Beispiel zeigt die Verwendung eines Ausgabeparameters und eines Verweises.
<Project>
<PropertyGroup>
<RoslynCodeTaskFactoryAssembly Condition="$(RoslynCodeTaskFactoryAssembly) == ''">$(MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll</RoslynCodeTaskFactoryAssembly>
</PropertyGroup>
<UsingTask
TaskName="MyInlineTask"
TaskFactory="RoslynCodeTaskFactory"
AssemblyFile="$(RoslynCodeTaskFactoryAssembly)">
<ParameterGroup>
<Input ParameterType="System.String" Required="true" />
<Output ParameterType="System.String" Output="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Text.Json" /> <!-- Reference an assembly -->
<Using Namespace="System.Text.Json" /> <!-- Use a namespace -->
<Code Type="Fragment" Language="cs">
<![CDATA[
Output = JsonSerializer.Serialize(new { Message = Input });
]]>
</Code>
</Task>
</UsingTask>
<Target Name="RunInlineTask">
<MyInlineTask Input="Hello, Roslyn!" >
<Output TaskParameter="Output" PropertyName="SerializedOutput" />
</MyInlineTask>
<Message Text="Serialized Output: $(SerializedOutput)" />
</Target>
</Project>