다음을 통해 공유


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 디자이너에서 식별 이름과 설명을 표시합니다.

모듈 프로젝트의 Properties 폴더 안에 "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 파일의 예입니다.

리소스 스크린샷

작업 및 매개 변수에 식별 이름과 설명을 빠르게 추가하는 또 다른 방법은 [Action], [InputArguement][OutputArguement] 특성의 FriendlyName 및 Description 속성을 사용하는 것입니다.

노트

모듈에 알기 쉬운 이름과 설명을 추가하려면 해당 .resx 파일을 수정하거나 해당 C# 특성을 추가해야 합니다.

리소스 지역화

데스크탑용 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
    }
}

Result 부울 변수를 확인합니다.

파일이 존재하는 경우 작업에 출력 인수가 없습니다. 반환되는 값은 부울 변수 Result가 보유하는 내용에 따라 true 또는 false입니다.

사용자 지정 작업 선택기

하나 이상의 변형이 있어야 사용자 지정 작업이 필요할 수 있는 특별한 경우가 있습니다.

예를 들어 표준 작업 라이브러리의 "Excel 실행" 작업이 있습니다.

"빈 문서 포함" 선택기를 사용하면 흐름이 빈 Excel 문서를 시작하는 반면 "다음 문서 열기" 선택을 사용하려면 열 파일의 파일 경로가 필요합니다.

Excel 실행 작업 선택기의 스크린샷

위에서 언급한 두 가지 작업은 "Excel 실행" 기본 작업의 두 가지 선택기입니다.

사용자 지정 작업을 만들 때 기능을 다시 작성할 필요가 없습니다.

하나의 "기본" 액션을 생성하고 입력 및 출력 매개 변수를 설정한 다음 액션 선택기를 활용하여 각 버전에 표시될 항목을 선택할 수 있습니다.

작업 선택기를 통해 단일 작업에 추상화 수준을 추가할 수 있으므로 매번 동일한 작업의 새로운 변형을 형성하기 위해 코드를 다시 작성할 필요 없이 단일 "기본" 작업에서 특정 기능을 검색할 수 있습니다.

선택자를 선택으로 생각하고 단일 작업을 필터링하고 각 선택자에 따라 필요한 정보만 표시합니다.

작업 선택기 다이어그램의 스크린샷

새 작업 선택기를 구성하려면 먼저 선택기가 사용할 기본 작업을 만듭니다.

중앙 작업에는 입력 C# 인수로 부울 또는 enum 속성이 필요합니다.

이 속성 값에 따라 사용되는 선택기가 결정됩니다.

가장 일반적인 방법은 열거형을 사용하는 것입니다. 특히 두 개 이상의 선택자가 필요한 경우 열거형이 유일한 옵션입니다.

두 가지 선택기의 경우 부울을 사용할 수 있습니다.

제약 조건 인수라고도 하는 이 속성에는 기본값이 있어야 합니다.

중앙 행동은 고전 행동으로 선언됩니다.

첫 번째 속성(입력 인수)은 열거형입니다. 해당 속성 값에 따라 적절한 선택기가 활성화됩니다.

노트

인수를 원하는 방식으로 정렬하려면 InputArgument 특성 옆에 있는 Order 값을 설정합니다.

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

노트

Selector 클래스는 작업으로 선언하면 안 됩니다. 유일한 조치는 중앙 조치입니다. 선택기는 필터 역할을 합니다.

이 특정 예에서는 인수 중 하나만 표시하려고 하므로 다른 인수는 필터링됩니다. 마찬가지로 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 컨텍스트) 메서드를 통해 이루어집니다. 선택기를 기준으로 필터링된 각 값이 표시됩니다.

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

또는 모든 .dll 파일을 반복하고 제공된 인증서로 각 파일에 서명하는 다음 명령을 실행합니다(Windows PowerShell 스크립트 .ps1 생성).

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은 데스크톱 흐름에서 사용할 수 없으며 포함하는 동안 오류가 발생합니다.

다음 단계

사용자 지정 작업 업로드