Actions SDK を使用してデスクトップ アクション用に Power Automate を作成する

この記事では、デスクトップ用 Power Automate でカスタム アクションを作成する方法について説明します。

カスタム アクションの作成

重要

予約されたキーワードは、アクション名やアクションのプロパティとして使用できません。 予約済みキーワードをアクション名やアクション プロパティとして使用すると、誤った動作が発生します。 詳細: デスクトップ フローの予約済みキーワード

新しいクラス ライブラリ (.NET Framework) プロジェクトを作成して開始する。 .NET Framework バージョン 4.7.2 選択します。

作成したカスタム モジュールでアクションを形成するには、次を実行します。

  • 自動生成されたクラス 1.cs ファイルを削除する。
  • プロジェクト内にカスタム アクションを表す新しいクラスを作成し、固有の名前を付ける。
  • Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK および Microsoft.PowerPlatform.PowerAutomate.Desktop.Actions.SDK.Attributes 名前空間を含める。
  • アクションを表すすべてのクラスは、クラスの上に [アクション] 属性を持つ必要があります。
  • このクラスにはパブリック アクセス許可があり、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# プロパティで表されます。 各プロパティには、そのタイプとデスクトップ用 Power Automate で表示される方法を指定する適切な C# 属性、[InputArgument] または [OutputArgument] が必要です。 入力引数には既定値を指定することもできます。

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 プロパティと説明プロパティで設定できます。

以下は、カスタム モジュール用の Resources.resx ファイルの例です。

リソースのスクリーンショット

フレンドリ名と説明をアクションとパラメータにすばやく追加する他の方法として、[アクション][InputArguement][OutputArguement] 属性で、FriendlyName プロパティと説明プロパティを使用することもできます。

注意

フレンドリ名と説明をモジュールに追加するには、それぞれの .resx ファイルを変更するか、それぞれの C# 属性を追加する必要があります。

リソースのローカライズ

デスクトップ用 Power Automate のモジュールの既定の言語は、おそらく英語です。

Resources.resx ファイルは英語である必要があります。

追加のローカライズ用 Resources.{locale}.resx ファイルを使用して他の言語を追加できます。 たとえば、Resources.fr.resx です。

カスタム モジュール カテゴリ

モジュールには、アクションを見つけやすくするためにカテゴリとサブカテゴリを含めることができます。

カテゴリ、サブカテゴリでカスタム アクションを分離するには、カスタム アクションを表すクラスの前にある [アクション] 属性を次の方法で変更します。

[Action(Category = "category.subcategory")]

注意

モジュールには、複数のカテゴリを含めることができます。 同様に、カテゴリはサブカテゴリで構成できます。 この構造は不定になる場合があります。

注文プロパティは、デザイナーでアクションをプレビューする順序を指定します。

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 の起動セレクターのスクリーンショット

上記の 2 つのアクションは、"Excel の起動" 基本アクションのセレクターです。

カスタム アクションを作成する場合、機能を再書き込みする必要はありません。

単一の "ベース" アクションを作成し、その入力パラメーターと出力パラメーターを設定してから、アクション セレクターを利用して各フレーバーに表示されるものを選択できます。

アクション セレクターを使用すると、単一のアクションに抽象化レベルを追加できるため、毎回コードを再書き込みして同じアクションの新しいバリエーションを形成することなく、単一の "ベース" アクションから特定の機能を取得できるようになります。

セレクターは、単一のアクションをフィルター処理し、それぞれのセレクターに応じて必要な情報のみを提示する選択肢であると考えてください。

アクション セレクターの図のスクリーンショット

新しいアクション セレクターを作成するには、まずセレクターで使用する基本アクションを作成します。

中心アクションには、入力 C# 引数としてブール値または列挙型プロパティのいずれかが必要です。

このプロパティの値によって、使用するセレクターが決定します。

最も一般的な方法は列挙型を使用することです。 特に 2 つ以上のセレクターが必要な場合は、列挙型が唯一のオプションです。

2 つのセレクターの場合、ブール値を使用できます。

このプロパティは制約引数とも呼ばれ、既定値が必要です。

中心的なアクションはクラシック アクションとして宣言されます。

最初のプロパティ (入力引数) が列挙型であることに注意してください。 そのプロパティの値に基づいて、適切なセレクターがアクティブになります。

注意

引数を好みの方法で順序付けするには、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
}

列挙型を使用したカスタム アクション セレクター

この例では、3 つのセレクターを作成します。 単純な列挙型により、毎回適切なセレクターが決まります。

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);
    }
}

注意

セレクター クラスはアクションとして宣言しないでください。 唯一のアクションは中心アクションです。 セレクターはフィルターとして機能します。

この特定の例では、引数の 1 つだけを表示するため、他の引数は除外されます。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 ファイルは、組織が信頼するデジタル証明書で適切に署名されている必要があります。 証明書は、カスタム アクションに依存するデスクトップ フローが作成/ 変更/ 実行される各コンピュータにもインストールされ、信頼されたルート証明機関の下に存在する必要があります。

カスタム モジュール ID

各モジュールには独自の ID (アセンブリ名) があります。 カスタム モジュールを作成するときは、必ず一意のモジュール ID を設定してください。 モジュールのアセンブリ名を設定するには、C# プロジェクトのプロパティの全般セクションにある アセンブリ名 プロパティを変更します。

警告

同じ ID を持つモジュールをフローに含めると競合が発生します

カスタム モジュール名の規則

カスタム モジュールをデスクトップ用 Power Automate で読み取れるようにするには、AssemblyName のファイル名が次のパターンに従う必要があります。

?*.Modules.?*
Modules.?*

たとえば、Modules.ContosoActions.dll

プロジェクト設定の AssemblyTitle はモジュール ID を指定します。 英数字とアンダースコアのみを使用でき、文字で始める必要があります。

カスタム モジュール内のすべての DLL に署名する

重要

カスタム モジュール (生成されたアセンブリとそのすべての依存関係) を構成するすべての .dll ファイルが、信頼できる証明書で署名されていることが必須です

カスタム モジュールの作成を完了するには、プロジェクトの bin/release フォルダーまたは bin/Debug フォルダーにある、生成されたすべての .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 スクリプトは、Windows PowerShell で呼び出して以下を提供することにより、.cab ファイルの作成に使用できます。

  • 圧縮する .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 はデスクトップ フローでは使用できず、含める際にエラーが発生します。

次の手順

カスタム アクションをアップロードする