Crea Power Automate per azioni desktop utilizzando le azioni SDK
Questo articolo descrive come creare azioni personalizzate in Power Automate per desktop.
Creazione di azioni personalizzate
Importante
Le parole chiave riservate non possono essere utilizzate come nomi di azioni e/o proprietà di azioni. L'uso di parole chiave riservate come nomi di azioni e/o proprietà di azioni determina un comportamento errato. Ulteriori informazioni: Parole chiave riservate nei flussi desktop
Inizia creando un nuovo progetto Libreria di classi (.NET Framework). Seleziona .NET Framework versione 4.7.2.
Per formare un'azione nel modulo personalizzato creato:
- Elimina il file Class1.cs generato automaticamente.
- Crea una nuova classe all'interno del tuo progetto per rappresentare l'azione personalizzata, assegnandole un nome distinto.
- Includi gli spazi dei nomi Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK e Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.Attributes.
- Tutte le classi che rappresentano azioni dovrebbero avere un attributo [Azione] sopra la tua classe.
- La classe dovrebbe avere accesso pubblico ed ereditare dalla 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 maggior parte delle azioni hanno parametri (input o output). I parametri di input e output sono rappresentati dalle proprietà C# classiche.
Ogni proprietà deve avere un attributo C# appropriato, [InputArgument]
o [OutputArgument]
per dettarne il tipo e il modo in cui vengono presentati in Power Automate per desktop.
Gli argomenti di input possono anche avere valori predefiniti.
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}";
}
}
}
Aggiunta di descrizioni alle azioni personalizzate
Aggiungi una descrizione e un nome descrittivo per i moduli e le azioni in modo che gli sviluppatori RPA sappiano come utilizzarli al meglio.
La finestra di progettazione di Power Automate per desktop mostra nomi descrittivi e descrizioni.
Puoi creare un file "Resources.resx" all'interno della cartella Proprietà del progetto del modulo. Il nuovo file ".resx" dovrebbe essere denominato "Resources.resx".
Il formato delle descrizioni dei moduli e delle azioni dovrebbe essere il seguente:
"Module_Description" o "Action_Description" e "Module_FriendlyName" o "Action_FriendlyName" rispettivamente nel campo del nome. La descrizione nel campo del valore.
Ti consigliamo inoltre di fornire descrizioni e nomi descrittivi per i parametri. Il loro formato dovrebbe essere il seguente: "Action_Parameter_Description", "Action_Parameter_FriendlyName".
Suggerimento
Si consiglia di indicare ciò che si sta descrivendo nel campo dei commenti (ad es. Modulo, Azione ecc.)
Questi possono anche essere impostati con le proprietà FriendlyName e Description degli attributi [InputArgument]
, [OutputArgument]
e [Action]
.
Ecco un esempio di un file Resources.resx per un modulo personalizzato.
Un altro modo per aggiungere rapidamente nomi descrittivi e descrizioni ad azioni e parametri è con le proprietà FriendlyName e Description negli attributi [Azione], [InputArguement] e [OutputArguement].
Nota
Per aggiungere un nome descrittivo e una descrizione a un modulo, è necessario modificare il rispettivo file con estensione resx o aggiungere i rispettivi attributi C#.
Aggiunta della gestione degli errori ad azioni personalizzate
Per definire eccezioni personalizzate nella tua azione, usa l'attributo [Throws("ActionError")]
sopra la classe di azione personalizzata. Ogni caso di eccezione che si desidera definire dovrebbe avere un proprio attributo.
Nel blocco catch, utilizza il seguente codice:
throw new ActionException("ActionError", e.Message, e.InnerException);
Assicurati che il nome ActionException
corrisponda al nome fornito Throws
nell'attributo. Utilizzare throw new ActionException
per ogni caso di eccezione e abbinarlo Throws
al nome dell'attributo corrispondente. Tutte le eccezioni definite con l'attributo Throws
sono visibili nella scheda di gestione degli errori delle azioni della finestra di progettazione.
Un esempio di ciò può essere trovato nella sezione Azioni condizionali.
Localizzazione delle risorse
La lingua predefinita per i moduli in Power Automate per desktop si presume sia inglese.
Il file Resources.resx deve essere in inglese.
Qualsiasi altra lingua può essere aggiunta con file Resources.{locale}.resx extra per la localizzazione. Ad esempio, Resources.fr.resx.
Categorie di modulo personalizzato
I moduli possono includere categorie e sottocategorie per una migliore organizzazione delle azioni.
Per separare le azioni personalizzate in categorie, sottocategorie, modifica l'attributo [Action] che precede la classe che rappresenta l'azione personalizzata nel modo seguente:
[Action(Category = "category.subcategory")]
Nota
Un modulo può avere più categorie. Allo stesso modo, le categorie possono essere composte da sottocategorie. Questa struttura può essere indefinita.
La proprietà Order determina l'ordine in base al quale le azioni vengono visualizzate in anteprima nella finestra di progettazione.
Action1
appartiene alla categoria "TestCategory" ed è la prima azione del modulo (in questo modo spieghi Ordine e categoria con un esempio).
[Action(Id = "Action1", Order = 1, Category = "TestCategory")]
Azioni per condizionali
Le azioni condizionali sono azioni che restituiscono "Vero" o "Falso". L'azione "Se il file esiste" di Power Automate per desktop della libreria standard è un buon esempio di azione condizionale.
Esempio di azione condizionale:
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
}
}
Nota la variabile booleana Risultato.
L'azione Se il file esiste non ha un argomento di output. Ciò che restituisce è vero o falso, a seconda di cosa contiene la variabile booleana Risultato .
Selettori di azione personalizzate
Ci sono casi particolari, in cui potrebbe essere necessario che un'azione personalizzata abbia più di una variante.
Un esempio è l'azione "Avvia Excel", dalla libreria di azioni standard.
Utilizzando il selettore "con un documento vuoto", il flusso avvia un documento Excel vuoto, mentre l'utilizzo della selezione "e apri il documento seguente" richiede l'apertura del percorso del file.
Le due azioni sopra menzionate sono due selettori dell'azione di base "Avvia Excel".
Quando crei azioni personalizzate, non devi riscrivere la funzionalità.
Puoi creare una singola azione "base", impostando i suoi parametri di input e output e quindi scegliere cosa sarebbe visibile in ogni sapore utilizzando i selettori di azione.
Attraverso i selettori di azione è possibile aggiungere un livello di astrazione su una singola azione, consentendo il recupero di funzionalità specifiche dalla singola azione "base" senza dover riscrivere il codice per formare ogni volta una nuova variante della stessa azione.
Pensa ai selettori come scelte, che filtrano una singola azione e presentano solo le informazioni richieste in base ai rispettivi selettori.
Per formare un nuovo selettore di azioni, crea prima un'azione di base che deve essere utilizzata dai selettori.
L'azione centrale richiede una proprietà booleana o di enumerazione come argomento C# di input.
Il valore di questa proprietà determina quale selettore viene utilizzato.
Il modo più comune è utilizzare un'enumerazione. Soprattutto quando sono necessari più di due selettori, enumerazione è l'unica opzione.
Per due casi di selettore, è possibile utilizzare valori booleani.
Questa proprietà, nota anche come argomento di vincolo, deve avere un valore predefinito.
L'azione centrale è dichiarata azione classica.
Si noti che la prima proprietà (argomento di input) è un'enumerazione. In base al valore di quella proprietà, il selettore appropriato diventa attivo.
Nota
Per ordinare gli argomenti nel modo desiderato, imposta il valore Ordine accanto all'attributo 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
}
Selettori di azioni personalizzate che utilizzano l'enumerazione
In questo esempio, crei tre selettori. Una semplice enumerazione determina ogni volta il selettore appropriato:
public enum SelectorChoice
{
Selector1,
Selector2,
Selector3
}
I selettori sono rappresentati da classi.
Tali classi devono ereditare la classe ActionSelector<TBaseActionClass>
.
Nota
TBaseActionClass è il nome della classe di azione di base.
Nel metodo UseName() , viene dichiarato il nome del selettore di azioni. Viene utilizzato come nome dell'azione per risolvere le risorse.
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);
}
}
Nota
Le classi Selettore non devono essere dichiarate come azioni. L'unica azione è quella centrale. I selettori fungono da filtri.
In questo esempio specifico vogliamo visualizzare solo uno degli argomenti, quindi gli altri vengono filtrati. Allo stesso modo per Selettore2:
public class Selector2 : ActionSelector<CentralCustomAction>
{
public Selector2()
{
UseName("DisplayFullName");
Prop(p => p.Selector).ShouldBe(SelectorChoice.Selector2);
ShowAll();
Hide(p => p.Age);
}
}
E le classiSelector3:
public class Selector3 : ActionSelector<CentralCustomAction>
{
public Selector3()
{
UseName("DisplayFullDetails");
Prop(p => p.Selector).ShouldBe(SelectorChoice.Selector3);
ShowAll();
}
}
L'esecuzione finale si ottiene attraverso il metodo Execute(ActionContext) che risiede nell'azione centrale. In base al selettore, vengono visualizzati i rispettivi valori filtrati.
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}";
}
}
Selettori di azioni personalizzate che utilizzano il valore booleano
Di seguito è riportato un esempio che utilizza i valori booleani anziché l'enumerazione.
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);
}
}
}
Descrizioni delle impostazioni per i selettori di azioni personalizzate
Per creare una descrizione e un riepilogo per i selettori, utilizza il seguente formato nel file .resx del tuo modulo personalizzato.
SelectorName_Description
SelectorName_Summary
Questa operazione può essere eseguita anche nel selettore con i metodi WithDescription e WithSummary.
Importante
I file .dll che descrivono le azioni personalizzate, le loro dipendenze .dll e il file .cab contenente tutto devono essere firmati correttamente con un certificato digitale considerato attendibile dalla tua organizzazione. Il certificato deve essere installato anche in ciascuna macchina su cui viene creato, modificato e/o eseguito il flusso desktop con le dipendenze delle azioni personalizzate, presente in Autorità di certificazione radice disponibile nell'elenco locale.
ID modulo personalizzati
Ogni modulo ha il proprio ID (nome dell'assembly). Quando crei moduli personalizzati, assicurati di impostare ID modulo univoci. Per impostare il nome dell'assembly del modulo, modifica la proprietà Nome assembly nella sezione Generale delle proprietà del progetto C#.
Avviso
L'inclusione di moduli con lo stesso ID in un flusso causa conflitti
Convenzioni sui nomi dei moduli personalizzati
Affinché i moduli personalizzati siano leggibili tramite Power Automate per desktop, AssemblyName deve avere un nome file che segua il modello seguente:
?*.Modules.?*
Modules.?*
Ad esempio, Modules.ContosoActions.dll
AssemblyTitle nelle impostazioni del progetto specifica l'ID del modulo. Può contenere solo caratteri alfanumerici e di sottolineatura e deve iniziare con una lettera.
Firma tutte le DLL all'interno del modulo personalizzato
Importante
È obbligatorio che tutti i file .dll che compongono un modulo personalizzato (assembly generato e tutte le sue dipendenze) siano firmati con un certificato attendibile
Per finalizzare la creazione del modulo personalizzato, tutti i file .dll generati, che si trovano nella cartella bin/release o bin/Debug del progetto, devono essere firmati.
Firma tutti i file con estensione dll utilizzando un certificato attendibile eseguendo il comando seguente (per ogni file con estensione dll) in un prompt dei comandi per gli sviluppatori per Visual Studio:
Firma tutti i file .dlls utilizzando un certificato attendibile eseguendo il comando seguente (per ciascuna dll) in un prompt dei comandi per gli sviluppatori per 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
oppure eseguendo il comando seguente (creando uno script Windows PowerShell .ps1) che scorre tutti i file .dll e firma ciascuno con il certificato fornito:
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
}
Nota
Il certificato digitale deve avere una chiave privata esportabile e funzionalità di firma del codice
Creazioe di un pacchetto file CAB con tutti gli elementi
Il file .dll contenente le azioni personalizzate e tutte le relative dipendenze (file .dll) deve essere compresso in un file CAB (.cab).
Nota
Quando si assegna un nome al file .cab, segui la convenzione di denominazione di file e cartelle per il sistema operativo Windows. Non utilizzare spazi vuoti o caratteri speciali come < > : " / \ | ? *
.
Crea uno script di Windows PowerShell (.ps1) contenente le seguenti righe:
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
Questo script di Windows PowerShell può quindi essere utilizzato per creare il file .cab richiamandolo in Windows PowerShell e fornendo:
- La directory dei file .dll da comprimere.
- La directory di destinazione in cui inserire il file .cab generato.
Invoca lo script utilizzando la sintassi seguente:
.\{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
Esempio:
.\makeCabFile.ps1 "C:\Users\Username\source\repos\MyCustomModule\bin\Release\net472" "C:\Users\Username\MyCustomActions" MyCustomActions.cab
Nota
- Assicurati che il file .dll delle azioni personalizzate effettive si trovi nel livello principale del percorso di destinazione durante la creazione del file .cab e non in una sottocartella.
- Anche il file .cab deve essere firmato. I file .cab non firmati e/o i file .dll non firmati in essi contenuti non saranno utilizzabili nei flussi desktop e genereranno errori durante l'inclusione.