Créer des actions Power Automate pour le bureau à l’aide du kit de développement logiciel Actions
Cet article explique comment créer des actions personnalisées dans Power Automate pour le bureau.
Créer des actions personnalisées
Important
Les mots clés réservés ne peuvent pas être utilisés comme noms d’action et/ou propriétés d’action. L’utilisation de mots clés réservés comme noms d’action et/ou propriétés d’action entraîne un comportement erroné. Pour plus d’informations : Mots clés réservés dans les flux de bureau
Commencez par créer un nouveau projet Bibliothèque de classes (.NET Framework). Sélectionnez .NET Framework version 4.7.2.
Pour former une action dans le module personnalisé créé :
- Supprimez le fichier Class1.cs généré automatiquement.
- Créez une nouvelle classe dans votre projet pour représenter l’action personnalisée et attribuez-lui un nom distinct.
- Incluez les espaces de noms Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK et Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.Attributes.
- Toutes les classes qui représentent des actions doivent avoir un attribut [Action] au-dessus de votre classe.
- La classe doit avoir un accès public et hériter de la classe ActionBase.
using System;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.Attributes;
namespace Modules.MyCustomModule
{
[Action(Id = "CustomAction")]
public class CustomAction : ActionBase
{
public override void Execute(ActionContext context)
{
throw new NotImplementedException();
}
}
}
La plupart des actions peuvent avoir des paramètres (entrée ou sortie). Les paramètres d’entrée et de sortie sont représentés par des propriétés C# classiques.
Chaque propriété doit avoir un attribut C# approprié, [InputArgument]
ou [OutputArgument]
, pour définir son type et la façon dont elles sont présentées dans Power Automate pour le bureau.
Les arguments d’entrée peuvent également avoir des valeurs par défaut.
using System.ComponentModel;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.Attributes;
namespace Modules.MyCustomModule
{
[Action(Id = "CustomAction")]
public class CustomAction : ActionBase
{
[InputArgument, DefaultValue("Developer")]
public string InputName { get; set; }
[OutputArgument]
public string DisplayedMessage { get; set; }
public override void Execute(ActionContext context)
{
DisplayedMessage = $"Hello, {InputName}";
}
}
}
Ajout de descriptions aux actions personnalisées
Ajoutez une description et un nom convivial pour les modules et les actions afin que les développeurs RPA sachent comment optimiser leur utilisation.
Le concepteur Power Automate pour le bureau affiche les noms conviviaux et les descriptions.
Vous pouvez créer un fichier « Resources.resx » dans le dossier Propriétés du projet de module. Le nouveau fichier « .resx » doit être nommé « Resources.resx ».
Le format des descriptions pour les modules et les actions doit se présenter comme suit :
« Module_Description » ou « Action_Description » et « Module_FriendlyName » ou « Action_FriendlyName » respectivement dans le champ de nom. La description dans le champ de valeur.
Nous vous recommandons également de fournir des descriptions et des noms conviviaux pour les paramètres. Leur format doit se présenter comme suit : « Action_Parameter_Description », « Action_Parameter_FriendlyName ».
Astuce
Il est recommandé d’indiquer ce que vous décrivez dans le champ de commentaire (par exemple, module, action, etc.)
Ceux-ci peuvent également être définis avec les propriétés FriendlyName et Description des attributs [InputArgument]
, [OutputArgument]
et [Action]
.
Voici un exemple de fichier Resources.resx pour un module personnalisé.
Il est également possible d’ajouter rapidement des noms conviviaux et des descriptions aux actions et paramètres en utilisant les propriétés FriendlyName et Description des attributs [Action], [InputArguement] et [OutputArguement].
Note
Pour ajouter un nom convivial et une description à un module, vous devez modifier le fichier .resx respectif ou ajouter les attributs C# respectifs.
Ajout de la gestion des erreurs aux actions personnalisées
Pour définir des exceptions personnalisées dans votre action, utilisez l’attribut [Throws("ActionError")]
situé au-dessus de la classe d’action personnalisée. Chaque cas d’exception que vous souhaitez définir doit avoir son propre attribut.
Dans le bloc catch, utilisez le code suivant :
throw new ActionException("ActionError", e.Message, e.InnerException);
Assurez-vous que le nom ActionException
correspond à celui que vous avez fourni dans l’attribut Throws
. Utilisez throw new ActionException
pour chaque cas d’exception et associez-le au nom d’attribut Throws
correspondant. Toutes les exceptions définies avec l’attribut Throws
sont visibles dans l’onglet Gestion des erreurs d’action du concepteur.
Vous trouverez un exemple dans la section Actions conditionnelles.
Localisation des ressources
La langue par défaut des modules dans Power Automate pour le bureau est censée être l’anglais.
Le fichier Resources.resx doit être en anglais.
Toute autre langue peut être ajoutée avec des fichiers Resources.{locale}.resx supplémentaires pour la localisation. Par exemple, Resources.fr.resx
Catégories de module personnalisé
Les modules peuvent inclure des catégories et des sous-catégories pour une meilleure organisation des actions.
Afin de séparer les actions personnalisées en catégories et sous-catégories, modifiez l’attribut [Action] qui précède la classe qui représente l’action personnalisée de la manière suivante :
[Action(Category = "category.subcategory")]
Note
Un module peut avoir plusieurs catégories. De même, les catégories peuvent être composées de sous-catégories. Cette structure peut être indéfinie.
La propriété Order définit l’ordre dans lequel les actions sont prévisualisées dans le concepteur.
Action1
appartient à la catégorie « TestCategory » et c’est la première action du module (vous expliquez ainsi l’ordre et la catégorie avec un exemple).
[Action(Id = "Action1", Order = 1, Category = "TestCategory")]
Actions conditionnelles
Les actions conditionnelles sont des actions qui renvoient « Vrai » ou « Faux ». L’action « Si le fichier existe » de Power Automate pour le bureau de la bibliothèque standard est un bon exemple d’action conditionnelle.
Exemple d’action conditionnelle :
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.Attributes;
using System;
using System.ComponentModel;
namespace Modules.CustomModule
{
[ConditionAction(Id = "ConditionalAction1", ResultPropertyName = nameof(Result))]
[Throws("ActionError")] // TODO: change error name (or delete if not needed)
public class ConditionalAction1 : ActionBase
{
#region Properties
public bool Result { get; private set; }
[InputArgument]
public string InputArgument1 { get; set; }
#endregion
#region Methods Overrides
public override void Execute(ActionContext context)
{
try
{
//TODO: add action execution code here
}
catch (Exception e)
{
if (e is ActionException) throw;
throw new ActionException("ActionError", e.Message, e.InnerException);
}
}
#endregion
}
}
Notez la variable booléenne Result.
L’action Si le fichier existe n’a pas d’argument de sortie. Elle renvoie vrai ou faux, selon le contenu de la variable booléenne Result.
Sélecteurs d’actions personnalisées
Il existe des cas particuliers où une action personnalisée peut nécessiter plusieurs variantes.
Un exemple est l’action « Lancer Excel » dans la bibliothèque standard d’actions.
Si vous utilisez le sélecteur « avec un document vierge », le flux lance un document Excel vide, tandis que l’utilisation de la sélection « et ouvrir le document suivant » nécessite le chemin d’accès du fichier à ouvrir.
Les deux actions mentionnées ci-dessus sont deux sélecteurs de l’action de base « Lancer Excel ».
Lors de la création d’actions personnalisées, il n’est pas nécessaire de réécrire la fonctionnalité.
Vous pouvez créer une seule action « de base », en définissant ses paramètres d’entrée et de sortie, puis choisir ce qui serait visible dans chaque version en utilisant des sélecteurs d’action.
Grâce aux sélecteurs d’action, un niveau d’abstraction peut être ajouté à une action unique, ce qui permet la récupération de la fonctionnalité spécifique à partir de la seule action « de base » sans avoir à réécrire le code pour former une nouvelle variation de la même action à chaque fois.
Considérez les sélecteurs comme des choix, qui filtrent une seule action et ne présentent que les informations requises en fonction des sélecteurs respectifs.
Pour former un nouveau sélecteur d’actions, créez d’abord une action de base à utiliser par les sélecteurs.
L’action centrale nécessite une valeur booléenne ou une propriété d’énumération comme argument C# d’entrée.
La valeur de cette propriété détermine quel sélecteur est utilisé.
L’approche la plus courante consiste à utiliser une énumération. En particulier lorsque plus de deux sélecteurs sont nécessaires, les énumérations sont la seule option.
Pour les cas avec deux sélecteurs, les valeurs booléennes peuvent être utilisées.
Cette propriété, également appelée argument de contrainte, doit avoir une valeur par défaut.
L’action centrale est déclarée comme une action classique.
Notez que la première propriété (argument d’entrée) est une énumération. En fonction de la valeur de cette propriété, le sélecteur approprié devient actif.
Note
Pour que les arguments soient triés de la manière souhaitée, vous définissez la valeur Order en regard de l’attribut InputArgument.
using System.ComponentModel;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Desktop.Actions.SDK;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Desktop.Actions.SDK.Attributes;
namespace Modules.CustomModule
{
[Action(Id = "CentralCustomAction")]
public class CentralCustomAction : ActionBase
{
#region Properties
[InputArgument, DefaultValue(SelectorChoice.Selector1)]
public SelectorChoice Selector { get; set; }
[InputArgument(Order = 1)]
public string FirstName { get; set; }
[InputArgument(Order = 2)]
public string LastName { get; set; }
[InputArgument(Order = 3)]
public int Age { get; set; }
[OutputArgument]
public string DisplayedMessage { get; set; }
#endregion
#region Methods Overrides
public override void Execute(ActionContext context)
{
if (Selector == SelectorChoice.Selector1)
{
DisplayedMessage = $"Hello, {FirstName}!";
}
else if (Selector == SelectorChoice.Selector2)
{
DisplayedMessage = $"Hello, {FirstName} {LastName}!";
}
else // The 3rd Selector was chosen
{
DisplayedMessage = $"Hello, {FirstName} {LastName}!\nYour age is: {Age}";
}
}
#endregion
} // you can see below how to implement an action selector
}
Sélecteurs d’actions personnalisées qui utilisent des énumérations
Dans cet exemple, vous créez trois sélecteurs. Une énumération simple définit le sélecteur approprié à chaque fois :
public enum SelectorChoice
{
Selector1,
Selector2,
Selector3
}
Les sélecteurs sont représentés par des classes.
Ces classes doivent hériter de la classe ActionSelector<TBaseActionClass>
.
Note
TBaseActionClass est le nom de la classe d’action de base.
Dans la méthode UseName(), le nom du sélecteur d’actions est déclaré. Il est utilisé comme nom de l’action pour résoudre les ressources.
public class Selector1 : ActionSelector<CentralCustomAction>
{
public Selector1()
{
UseName("DisplayOnlyFirstName");
Prop(p => p.Selector).ShouldBe(SelectorChoice.Selector1);
ShowAll();
Hide(p => p.LastName);
Hide(p => p.Age);
// or
// Show(p => p.FirstName);
// Show(p => p.DisplayedMessage);
}
}
Note
Les classes Selector ne doivent pas être déclarées comme actions. La seule action est l’action centrale. Les sélecteurs agissent comme des filtres.
Dans cet exemple spécifique, nous voulons afficher un seul des arguments ; par conséquent, les autres sont filtrés. De même pour Selector2 :
public class Selector2 : ActionSelector<CentralCustomAction>
{
public Selector2()
{
UseName("DisplayFullName");
Prop(p => p.Selector).ShouldBe(SelectorChoice.Selector2);
ShowAll();
Hide(p => p.Age);
}
}
Et les classes Selector3 :
public class Selector3 : ActionSelector<CentralCustomAction>
{
public Selector3()
{
UseName("DisplayFullDetails");
Prop(p => p.Selector).ShouldBe(SelectorChoice.Selector3);
ShowAll();
}
}
L’exécution finale est réalisée par la méthode Execute(ActionContext context) qui réside dans l’action centrale. En fonction du sélecteur, les valeurs respectives filtrées sont affichées.
public override void Execute(ActionContext context)
{
if (Selector == SelectorChoice.Selector1)
{
DisplayedMessage = $"Hello, {FirstName}!";
}
else if (Selector == SelectorChoice.Selector2)
{
DisplayedMessage = $"Hello, {FirstName} {LastName}!";
}
else // The 3rd Selector was chosen
{
DisplayedMessage = $"Hello, {FirstName} {LastName}!\nYour age is: {Age}";
}
}
Sélecteurs d’actions personnalisées qui utilisent des valeurs booléennes
Voici un exemple qui utilise des valeurs booléennes au lieu d’énumérations.
using System.ComponentModel;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.ActionSelectors;
using Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.Attributes;
namespace Modules.CustomModule
{
[Action]
public class CentralCustomActionWithBoolean : ActionBase
{
#region Properties
[InputArgument, DefaultValue(true)]
public bool TimeExpired { get; set; }
[InputArgument]
public string ElapsedTime { get; set; }
[InputArgument]
public string RemainingTime { get; set; }
[OutputArgument]
public string DisplayedMessage { get; set; }
#endregion
#region Methods Overrides
public override void Execute(ActionContext context)
{
DisplayedMessage = TimeExpired ? $"The timer has expired. Elapsed time: {ElapsedTime}" : $"Remaining time: {RemainingTime}";
}
#endregion
}
public class NoTime : ActionSelector<CentralCustomActionWithBoolean>
{
public NoTime()
{
UseName("TimeHasExpired");
Prop(p => p.TimeExpired).ShouldBe(true);
ShowAll();
Hide(p => p.RemainingTime);
}
}
public class ThereIsTime : ActionSelector<CentralCustomActionWithBoolean>
{
public ThereIsTime()
{
UseName("TimeHasNotExpired");
Prop(p => p.TimeExpired).ShouldBe(false);
ShowAll();
Hide(p => p.RemainingTime);
}
}
}
Définition des descriptions pour les sélecteurs d’actions personnalisées
Pour créer une description et un résumé pour les sélecteurs, utilisez le format suivant dans le fichier .resx de votre module personnalisé.
SelectorName_Description
SelectorName_Summary
Cette opération peut également être effectuée dans le sélecteur avec les méthodes WithDescription et WithSummary.
Important
Les fichiers .dll qui décrivent les actions personnalisées, leurs dépendances .dll et le fichier .cab contenant tout doivent être correctement signés avec un certificat numérique approuvé par votre organisation. Le certificat doit également être installé sur chaque ordinateur sur lequel un flux de bureau avec des dépendances d’actions personnalisées est créé/modifié/exécuté, présent sous Autorités de certification racines de confiance.
ID de modules personnalisés
Chaque module possède son propre ID (nom de l’assembly). Lors de la création de modules personnalisés, assurez-vous de définir des ID de module uniques. Pour définir le nom d’assembly de votre module, modifiez la propriété Nom de l’assembly sous la section Général des propriétés du projet C#.
Avertissement
Inclure des modules avec le même ID dans un flux génère des conflits
Conventions d’affectation de noms de modules personnalisés
Pour que les modules personnalisés soient lisibles via Power Automate pour le bureau, AssemblyName doit avoir un nom de fichier qui suit le modèle ci-dessous :
?*.Modules.?*
Modules.?*
Par exemple, Modules.ContosoActions.dll
AssemblyTitle dans les paramètres du projet spécifie l’ID de module. Il ne peut contenir que des caractères alphanumériques et des traits de soulignement et doit commencer par une lettre.
Signer toutes les DLL dans le module personnalisé
Important
Il est obligatoire d’avoir tous les fichiers .dll qui composent un module personnalisé (assembly généré et toutes ses dépendances) signés avec un certificat de confiance
Pour finaliser la création du module personnalisé, tous les fichiers .dll générés, qui se trouvent sous le dossier bin/release ou bin/Debug du projet, doivent être signés.
Signez tous les fichiers .dll à l’aide d’un certificat approuvé en exécutant la commande suivante (pour chaque fichier .dll) dans une invite de commande du développeur pour Visual Studio :
Signez les fichiers .dll à l’aide d’un certificat approuvé en exécutant la commande suivante (pour chaque dll) dans une invite de commande du développeur pour Visual Studio :
Signtool sign /f {your certificate name}.pfx /p {your password for exporting the certificate} /fd
SHA256 {path to the .dll you want to sign}.dll
ou en exécutant la commande suivante (en créant un script Windows PowerShell .ps1) qui parcourt tous les fichiers .dll et signe chacun avec le certificat fourni :
Get-ChildItem {the folder where dll files of custom module exist} -Filter *.dll |
Foreach-Object {
Signtool sign /f {your certificate name}.pfx /p {your password for exporting the certificate} /fd SHA256 $_.FullName
}
Note
Le certificat numérique doit avoir une clé privée exportable et des fonctionnalités de signature de code
Compression de tous les éléments dans un fichier CAB
Le .dll contenant les actions personnalisées et toutes ses dépendances (fichiers .dll) doit être regroupé dans un fichier CAB (.cab).
Note
Lorsque vous nommez le fichier .cab, suivez la convention d’affectation de noms de fichiers et dossiers pour le système d’exploitation Windows. N’utilisez pas d’espaces vides ni de caractères spéciaux tels que < > : " / \ | ? *
.
Créez un script Windows PowerShell (.ps1) contenant les lignes suivantes :
param(
[ValidateScript({Test-Path $_ -PathType Container})]
[string]
$sourceDir,
[ValidateScript({Test-Path $_ -PathType Container})]
[string]
$cabOutputDir,
[string]
$cabFilename
)
$ddf = ".OPTION EXPLICIT
.Set CabinetName1=$cabFilename
.Set DiskDirectory1=$cabOutputDir
.Set CompressionType=LZX
.Set Cabinet=on
.Set Compress=on
.Set CabinetFileCountThreshold=0
.Set FolderFileCountThreshold=0
.Set FolderSizeThreshold=0
.Set MaxCabinetSize=0
.Set MaxDiskFileCount=0
.Set MaxDiskSize=0
"
$ddfpath = ($env:TEMP + "\customModule.ddf")
$sourceDirLength = $sourceDir.Length;
$ddf += (Get-ChildItem $sourceDir -Filter "*.dll" | Where-Object { (!$_.PSIsContainer) -and ($_.Name -ne "Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.dll") } | Select-Object -ExpandProperty FullName | ForEach-Object { '"' + $_ + '" "' + ($_.Substring($sourceDirLength)) + '"' }) -join "`r`n"
$ddf | Out-File -Encoding UTF8 $ddfpath
makecab.exe /F $ddfpath
Remove-Item $ddfpath
Ce script Windows PowerShell peut ensuite être utilisé pour créer le fichier .cab en l’appelant dans Windows PowerShell et en fournissant :
- Le répertoire des fichiers .dll à compresser.
- Le répertoire cible où placer le fichier .cab généré.
Appelez le script en utilisant la syntaxe suivante :
.\{name of script containing the .cab compression directions}.ps1 "{absolute path to the source directory containing the .dll files}" "{target dir to save cab}" {cabName}.cab
Exemple :
.\makeCabFile.ps1 "C:\Users\Username\source\repos\MyCustomModule\bin\Release\net472" "C:\Users\Username\MyCustomActions" MyCustomActions.cab
Note
- Assurez-vous que le fichier .dll des actions personnalisées réelles se trouve au niveau racine du chemin d’accès ciblé lors de la création du fichier .cab et non dans un sous-dossier.
- Le fichier .cab doit également être signé. Les fichiers .cab non signés et/ou les fichiers .dll non signés qui y sont contenus ne sont pas utilisables dans les flux de bureau et génèrent une erreur lors de l’inclusion.
Étapes suivantes
Charger les actions personnalisées