Skip to main content
Custom Tasks

How to create a custom Frends Task.

Ossi Galkin avatar
Written by Ossi Galkin
Updated over 6 months ago

Quick start

We have Task template that will create a ready to go Visual Studio solution. It can be packed to a NuGet package and uploaded to Frends. You can use your prefered C# IDE, such as Visual Studio, VS Code or Rider.

Creating a Frends Task Package

Frends fully supports creating your own Task packages. To do this you must create a .NET class library which is then wrapped in a NuGet package file and uploaded into Frends through the Tasks page.

To create a Frends Task you first need to create a .NET class library, preferably multi-targeting .NET Standard 2.0 and .NET Framework 4.7.1, so it will work on both Windows and Linux based agents.

Frends supports .NET Standard 2.0 and .NET Framework 4.7.1 class libraries starting from version 5.0. Previous Frends versions supported only libraries targeting .NET Framework up to 4.5.2, so if you need to be able to run on older Frends versions, you need to target .NET 4.5.2.

When creating the class library, please note that the task should be implemented as a public static method with a return value. Non-static methods or methods with no return value (void) cannot be used as tasks. The methods cannot be overloaded, e.g. you cannot have Frends.TaskLibrary.CreateFile(string filePath) and Frends.TaskLibrary.CreateFile(string filePath, bool overwrite).

Packaging the newly created Tasks.

Task libraries are distributed as NuGet packages (.nupkg). The assembly name and package Id must be identical, e.g. Frends.TaskTemplate.dll and Frends.TaskTemplate.1.0.0.0.nupkg.

Usually, Task can be packed using command dotnet pack but sometimes, usually when working with legacy code, you need to use nuget.exe and .nuspec files to pack the task.

Task parameters

All parameters specified for the method will be used as Task Parameters. If the parameter is of class type, it will be initialized as a structure.

For Example:

using System.ComponentModel;

namespace Frends.TaskLibrary
{
/// <summary>
/// File action type (nothing/delete/rename/delete)
/// </summary>
public enum ActionType
{
/// <summary>
/// Nothing is done to the file
/// </summary>
Nothing,

/// <summary>
/// File will be deleted
/// </summary>
Delete,
/// <summary>
/// File will be renamed
/// </summary>
Rename,

/// <summary>
/// File will be moved
/// </summary>
Move
}

/// <summary>
/// File class
/// </summary>
public class File
{
/// <summary>
/// File path
/// </summary>
[DefaultValue("\"C:\\Temp\\myFile.json\"")]
public string Path { get; set; }

/// <summary>
/// Maximum size of the file
/// </summary>
[DefaultValue("0")]
public int MaxSize { get; set; }


/// <summary>
/// Password for unlocking the file
/// </summary>
[PasswordPropertyText]
public string Password { get; set; }
}

/// <summary>
/// FileAction class defines what will be done to the file
/// </summary>
public class FileAction
{
/// <summary>
/// Action to be done with the file
/// </summary>
public ActionType Action { get; set; }

/// <summary>
/// If ActionType is Move or Rename then To is the path to be used
/// </summary>
[DefaultValue("\"\"")]
public string To { get; set; }
}

public static class Files
{
/// <summary>
/// DoFileAction task does the desired action to file
/// </summary>
/// <param name="file">File to handle</param>
/// <param name="action">Action to perform</param>
/// <returns>Returns information if task was successful</returns>
public static string DoFileAction(File file, FileAction action)
{
// TODO: change logic
return $"Input values. Path: '{file.Path}', Max size: '{file.MaxSize}', Action: '{action.Action}', To: '{action.To}'";
}
}
}

In case of a complex or large parameter structure you can use custom attributes from ComponentModel library. Use assets in System.ComponentModel and System.ComponentModel.DataAnnotations namespaces to specify how the parameters are shown in the UI. For .NET Standard 2.0 task libraries, the attributes are available from the System.ComponentModel.Annotations NuGet package.

Custom attributes from System.ComponentModel.DataAnnotations are supported from Frends version 4.5.6.

Default value: DefaultValueAttribute

Task parameters may use the DefaultValueAttribute to provide a default value which is shown in the editor, remember that the parameters are expressions in the editor and default values need to be provided as such, e.g. "true" for a boolean value, "\"C:\Temp\\"" for a string containing a filePath.

Sensitive information not to be logged: PasswordPropertyTextAttribute

Also, if a parameter should not be logged, the PasswordPropertyTextAttribute should be added. The value of the parameter will be replaced with << Secret >> in the log. Parameters may have a more complex hierarchical structure, we recommend using at most only two levels of hierarchy.

Optional inputs: UIHintAttribute

[UIHint(nameof(Property),"", conditions: object[]]

Show or hide editor inputs based on the value of other inputs.

Example:

public bool Rename { get; set; }
[UIHint(nameof(Rename),"", true)]
public string NewFileName { get; set; }

The NewFileName field will only be visible if the Rename property has the value true.

public FileEnum FileOptions { get; set; }
[UIHint(nameof(FileOptions),"", FileEnum.Rename, FileEnum.CreateNew)]
public string NewFileName { get; set; }

The NewFileName field will only be visible if the FileOptions choise is either Rename or CreateNew

Default editor type: DisplayFormatAttribute

[DisplayFormat(DataFormatString = "")]

Sets the default editor input type. The parameter input editor will try to use this format when e.g. filling out new task parameters.

Possible values for DataFormatString are:

  • Json

  • Text

  • Xml

  • Sql

  • Expression

Example:

[DisplayFormat(DataFormatString = "Sql")]
public string Query { get; set; }

Tabbed parameter panels: PropertyTabAttribute

[PropertyTab]

Group parameters as tabs

Example:

public static bool Delete([PropertyTab] string fileName, [PropertyTab] OptionsClass options)

Customize task discovery in FrendsTaskMetadata.json

By adding a FrendsTaskMetadata.json file to the root of the NuGet package, unwanted static methods can be skipped by listing only methods which are wanted as Tasks. For example the following json structure would only cause the DoFileAction to be considered as a Task:

{
"Tasks": [
{
"TaskMethod": "Frends.TaskLibrary.FileActions.DoFileAction"
}
]
}

XML Documentation

Custom Tasks can also be commented/documented in the code by using XML Documentation comments. These comments will show up in the process task editor automatically if the documentation XML file is included inside the Task NuGet (if the nuget Id is Frends.TaskLibrary then a file Frends.TaskLibrary.xml will be searched).

Generation of this file can be done automatically by enabling - Build/Ouput/ XML documentation from Visual Studio for example. When the comments are being queried, the Task Parameter definition is checked first and if this is not found then the type definition will be checked.

Did this answer your question?