使用 Actions SDK 建立電腦版 Power Automate 動作
本文介紹如何在桌面版 Power Automate 中建立自訂動作。
建立自訂動作
重要
保留關鍵字不能當作動作名稱和/或動作屬性。 使用保留關鍵字作為動作名稱和/或動作屬性會導致錯誤的行為。 詳細資訊:桌面流程中的保留關鍵字
先建立新的類別庫 (.NET Framework) 專案。 選取 .NET framework 版本 4.7.2。
若要在建立的自訂模組中形成動作:
- 請刪除自動產生的 Class1.cs 檔案。
- 在專案中建立新類別以代表自訂動作,並為其指定不同的名稱。
- 包括 Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK 和 Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.Attributes 命名空間。
- 所有代表動作的類別都應在類別上有 [Action] 屬性。
- 此類別應具備公用存取權,並從 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();
}
}
}
大部分動作都有參數 (輸入或輸出)。 輸入和輸出參數由類別 C# 屬性表示。
每個屬性都應該有適當的 C# 屬性,[InputArgument]
或 [OutputArgument]
表示其類型以及它們如何呈現在電腦版 Power Automate 中。
輸入引數也可以有預設值。
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}";
}
}
}
新增自訂動作的描述
為模組和動作新增描述及自訂名稱,讓 RPA 開發人員知道如何使用它們。
電腦版 Power Automate 設計工具會顯示自訂名稱和描述。
您可以在模組專案的 [屬性] 資料夾中建立「Resources.resx」檔案。 新的「.resx」檔案應命名為「Resources.resx」。
模組和動作的描述格式如下:
在 [名稱] 欄位中分別有「Module_Description」或「Action_Description」與「Module_FriendlyName」或「Action_FriendlyName」。 值欄位中的描述。
我們也建議您提供參數的描述和自訂名稱。 其格式應如下所示:「Action_Parameter_Description」、「Action_Parameter_FriendlyName」。
提示
建議在 [留言] 欄位 (例如模組,動作等) 中註明您所描述的內容。
也可以使用 [InputArgument]
、[OutputArgument]
和 [Action]
屬性的 FriendlyName 和 Description 屬性進行設定。
以下是自訂模組的 Resources.resx 檔案範例。
另一種快速將自訂名稱及描述新增至動作和參數的方式,是使用 [動作]、[InputArguement] 和 [OutputArguement] 屬性中的 FriendlyName 及描述屬性。
注意
若要將易記名稱和描述新增至模組,您必須修改對應的 .resx 檔案或新增對應的 C# 屬性。
在自訂動作中新增錯誤處理
若要在動作中定義自訂例外狀況,請使用自訂動作類別上方的 [Throws("ActionError")]
屬性。 您想要定義的每個例外狀況情況都應該有自己的屬性。
在 catch 區塊中,使用以下程式碼:
throw new ActionException("ActionError", e.Message, e.InnerException);
確保 ActionException
名稱與您在 Throws
屬性中提供的名稱相符。 對每個例外情況使用 throw new ActionException
,並將其與對應的Throws
屬性名稱相符。 使用 Throws
屬性定義的所有例外狀況,都會顯示在設計器的動作錯誤處理標籤中。
可以在條件式動作區段找到這樣的範例。
資源當地語系化
在電腦版 Power Automate 中模組的預設語言為英文。
Resources.resx 檔案應為英文。
您可以使用額外的 Resources.{locale}.resx 檔案來新增其他語言進行當地語系化。 例如 Resources.fr.resx。
自訂模組類別
模組可以包含類別及子類別,以更好地組織動作。
為了區分類別、子類別中的自訂動作,請按照以下方式修改表示自訂動作類別前的[Action] 屬性:
[Action(Category = "category.subcategory")]
注意
模組可以有多個類別。 同樣地,類別可以由子類別所組成。 此結構沒有限制。
Order 屬性會指示在設計工具中預覽動作的順序。
Action1
屬於「TestCategory」類別,它是模組的第一個動作 (這樣您可以用範例解釋順序和類別)。
[Action(Id = "Action1", Order = 1, Category = "TestCategory")]
條件動作
條件動作是指傳回「True」或「False」的動作。 標準程式庫的「如果檔案已存在」電腦版 Power Automate 動作,就是條件動作的好例子。
條件動作範例:
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
}
}
請注意結果布林值變數。
如果檔案已存在動作不具有輸出引數。 傳回的是 True 或 False,是根據布林值變數結果中的內容而定。
自訂動作選取器
在特定案例中,自訂動作可能需要多個變體。
例如,來自標準動作庫中的「啟動 Excel」動作。
使用「使用空白文件」選取器,流程會啟動空白 Excel 文件,而使用「開啟以下文件」選項則需要打開檔案的檔案路徑。
上述的兩個動作為「啟動 Excel」基本動作的兩個選取器。
建立自訂動作時,您不必重寫功能。
您可以建立單一「基本」動作、設定其輸入和輸出參數,然後使用動作選取器來選擇每個風格中可看到的內容。
透過動作選取器可以在單一動作上新增抽象層級,允許從單一「基本」動作中擷取特定功能,而不必每次都重寫代碼以形成相同動作的新變體。
將選取器視為選項,篩選單一動作並根據各自的選取器僅顯示所需的資訊。
若要建立新的動作選取器,請先建立供選取器使用的基本動作。
中心動作需要布林值或列舉屬性做為輸入 C# 引數。
此屬性的值會決定使用哪種選取器。
最常見的方式是使用列舉。 尤其是當需要超過兩個選取器時,只能選擇列舉。
如果是兩個選取器,則可以使用布林值。
這個屬性 (也稱為限制引數) 必須有預設值。
中心動作會宣告為傳統動作。
請注意,第一個屬性 (輸入引數) 是列舉。 根據該屬性的值,會將適當的選取器變成使用中狀態。
注意
若要讓引數以您想要的方式排序,請在 [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
}
使用列舉的自訂動作選取器
在此範例中,您將建立三個選取器。 簡單的列舉每次都會指示適當的選取器:
public enum SelectorChoice
{
Selector1,
Selector2,
Selector3
}
選取器是依類別表示。
這些類別必須繼承 ActionSelector<TBaseActionClass>
類別。
注意
TBaseActionClass 是基本動作類別名稱。
在 UseName () 方法中,已宣告動作選取器的名稱。 這是用來解析資源之動作的名稱。
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);
}
}
注意
選取器類別不應宣告為動作。 唯一的動作是中心動作。 選取器當做篩選器。
在此特定範例中,我們只想顯示其中一個引數,因此其他的會被篩選掉。類似 Selector2:
public class Selector2 : ActionSelector<CentralCustomAction>
{
public Selector2()
{
UseName("DisplayFullName");
Prop(p => p.Selector).ShouldBe(SelectorChoice.Selector2);
ShowAll();
Hide(p => p.Age);
}
}
與 Selector3 類別:
public class Selector3 : ActionSelector<CentralCustomAction>
{
public Selector3()
{
UseName("DisplayFullDetails");
Prop(p => p.Selector).ShouldBe(SelectorChoice.Selector3);
ShowAll();
}
}
最後執行是透過位於中心動作中的 Execute(ActionContext context) 方法來完成。 根據選取器,會顯示篩選後的相應值。
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}";
}
}
使用布林值的自訂動作選取器
以下是使用布林值而不是列舉的範例。
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);
}
}
}
自訂動作選取器的設定描述
若要建立選取器的描述和摘要,請在自訂模組的 .resx 檔案中使用以下格式。
SelectorName_Description
SelectorName_Summary
這也可以在帶有 WithDescription 和 WithSummary 方法的選取器中完成。
重要
描述自訂動作的 .dll 檔案、其 .dll 相依性以及包含所有內容的 .cab 檔案,都應該正確地使用組織所信任的數位憑證進行簽署。 該憑證還應安裝在撰寫/修改/執行具有自訂動作相依性桌面流程的每台電腦上,並存在於信任的根憑證授權下。
自訂模組識別碼
每個模組都有自己的識別碼 (組件名稱)。 建立自訂模組時,請確定您已設定唯一的模組識別碼。 若要設定模組的組件名稱,請修改 C# 專案屬性「一般」區段下的組件名稱屬性。
警告
在流程中包含具有相同識別碼的模組將會導致衝突
自訂模組名稱慣例
若要透過電腦版 Power Automate 讀取自訂模組,AssemblyName 的檔案名必須遵循以下模式:
?*.Modules.?*
Modules.?*
例如,Modules.ContosoActions.dll
專案設定中的 AssemblyTitle 會指定模組識別碼。 其只能包含英數字元和底線,而且必須以字母開頭。
簽署自訂模組中的所有 DLL
重要
必須使用可信任憑證對構成自訂模組 (產生的組件及其所有相依性) 的所有 .dll 檔案進行簽署
若要完成自訂模組的建立,必須對所有產生的 .dll 檔案 (可在專案的間隔/版本或間隔/偵錯資料夾下找到) 進行簽署。
透過在 Visual Studio 開發人員命令提示字元中執行以下命令 (針對每個 .dll 檔案),使用受信任的憑證對所有 .dll 檔案進行簽署:
透過在 Visual Studio 開發人員命令提示字元中執行以下命令 (針對每個 dll),使用受信任的憑證簽署 .dll 檔案:
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
或透過執行以下命令 (透過建立 Windows PowerShell 指令碼 .ps1) 來迭代所有 .dll 檔案,並使用提供的憑證簽署檔案:
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
}
注意
數位憑證需具有可匯出私密金鑰和程式碼簽署功能
將所有內容封裝在封包檔中
包含自訂動作及其所有相依性 (.dll 檔案) 的 .dll 必須封裝在封包檔 (.cab) 中。
注意
命名 .cab 檔案時,請遵循 Windows 作業系統的檔案和資料夾命名慣例。 請勿使用空格或特殊字元,例如 < > : " / \ | ? *
。
建立包含以下各行的 Windows PowerShell 指令碼 (ps1):
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
您可以使用此 Windows PowerShell 指令碼建立 .cab 檔案,方法是在 Windows PowerShell 中叫用它並提供:
- 要壓縮的 .dll 檔案的目錄。
- 放置產生的 .cab 檔案的目標目錄。
使用下列語法,叫用指令碼:
.\{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
範例:
.\makeCabFile.ps1 "C:\Users\Username\source\repos\MyCustomModule\bin\Release\net472" "C:\Users\Username\MyCustomActions" MyCustomActions.cab
注意
- 建立 .cab 檔案時,確保實際自訂動作 .dll 檔案位於目標路徑的根層級,而不是子資料夾。
- .Cab 檔案也必須經過簽署。 其中包含的未簽署 .cab 檔案和 (或) 未簽署 .dll 將無法在桌面流程中使用,並將在包含過程中造成錯誤。