RPAにおけるインテグレーションのためのライブラリ開発

2020年3月5日(木)
井上 秀和

Visual Studioでの開発

Visual Studioを起動し、新規プロジェクト(New Project)より「Visual C#」=>「Window Desktop」=>「Class Library (.NET Framework)」を選択します。名前を「AwsS3Activity」として、「OK」で進みます。

新規プロジェクトの作成

新規プロジェクトの作成

始めにCustom Activityの開発に必要となるライブラリを追加します。「Project」より、「Add Reference...」を選択します。

ライブラリの追加

ライブラリの追加

「Reference Manager」の「Assemblies」にて、System.ActivitiesおよびSystem.ComponentModel.Compositionの参照を検索して選択し、プロジェクトに取り込みます。

選択したライブラリをプロジェクトに取り込む

選択したライブラリをプロジェクトに取り込む

続いて、AWSのNuGetパッケージを取り込むため、NuGet Package Managerを開きます。検索窓で、「AWSSDK.S3」を検索します。「AWSSDK.S3」を選択し、「Install」を実行します。依存関係のある「AWSSDK」と「AWSSDK.S3」がインストールされ、プロジェクトから参照可能となります。

AWSSDK.S3を取り込む

AWSSDK.S3を取り込む

「AwsS3Activity.cs」という名称でソースファイルを追加します。まずは、このような形でActivity開発の枠組みだけを作成しておきます。

カスタムアクティビティの作成には、CodeActivityクラスを継承する必要があります。protected override void Execute(CodeActivityContext context)メソッドをオーバーライドしたもので、こちらのメソッドが、UiPathのアクティビティで実行される際に呼ばれるメソッドとなります。

リスト3:CodeActivityクラスを継承したメソッドの作成

using System;
using System.Activities;
using System.ComponentModel;

namespace UiPathTeam.AwsS3
{
    public class AwsS3Activity : CodeActivity
    {
        protected override void Execute(CodeActivityContext context)
        {

        }
    }
}

カスタムアクティビティの開発準備は今しばらく続きます。あらかじめ単体テストの準備をしておきましょう。Visual Studioで別のプロジェクトとして「Add New Project」より、単体テスト用のプロジェクトを作成します。「Visual C#」=>「Test」=>「Unit Test Project (.NET Framework)」を選択し、「UnitTestAwsS3Activity」という名称とします。

単体テスト用プロジェクトを作成

単体テスト用プロジェクトを作成

この「UnitTestAwsS3Activity」からは、「AwsS3Activity」を参照するため、「Reference Manager」の「Projects」より、「AwsS3Activity」にチェックを入れ、「OK」より参照関係を確立します。

テスト用プロジェクトとの参照関係を確立

テスト用プロジェクトとの参照関係を確立

「UnitTest1.cs」という単体テスト用のファイルを作り、「AwsS3Activity」の実装は空っぽですが、ひとまず、単体テストが稼働するか確認しておきます。

単体テストの動作確認

単体テストの動作確認

それでは、「AwsS3Activity」プロジェクトに戻り、実装を行います。Activityとして受け付ける引数は、下記の通りです。

AwsS3Activityの引数

方向パラメータ説明
入力BucketNameStringS3のバケット名
入力KeyNameStringアップロード先のキー名称
入力FilePathStringアップロード対象のファイルパス
入力AccessKeyStringAccessキー
入力SecretKeyStringSecretキー
入力BucketRegionStringリージョン情報

実装はこのような形になります。

リスト4:AwsS3Activity

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// for custom activity implementation
using System.Activities;
using System.ComponentModel;

// for AWS
using Amazon.S3;
using Amazon.S3.Transfer;
using System.IO;

namespace UiPathTeam.AwsS3
{
    public class AwsS3Activity : CodeActivity
    {

        [Category("Input")]
        [RequiredArgument]
        public InArgument<string> BucketName { get; set; }

        [Category("Input")]
        [RequiredArgument]
        public InArgument<string> KeyName { get; set; }

        [Category("Input")]
        [RequiredArgument]
        public InArgument<string> FilePath { get; set; }

        [Category("Input")]
        [RequiredArgument]
        public InArgument<string> AccessKey { get; set; }

        [Category("Input")]
        [RequiredArgument]
        public InArgument<string> SecretKey { get; set; }

        [Category("Input")]
        [RequiredArgument]
        public InArgument<Amazon.RegionEndpoint> BucketRegion { get; set; }

        static string profileName = "default";
        private static IAmazonS3 s3Client;

        private void UploadFile(string bucketName, string keyName, string filePath)
        {
            try
            {
                var fileTransferUtility = new TransferUtility(s3Client);
                fileTransferUtility.Upload(filePath, bucketName, keyName);
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
                throw e;
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
                throw e;
            }
        }

        protected override void Execute(CodeActivityContext context)
        {
            var bucketName = BucketName.Get(context);
            var keyName = KeyName.Get(context);
            var filePath = FilePath.Get(context);
            var accessKey = AccessKey.Get(context);
            var secretKey = SecretKey.Get(context);
            var bucketRegion = BucketRegion.Get(context);

            Amazon.Util.ProfileManager.RegisterProfile(profileName, accessKey, secretKey);
            s3Client = new AmazonS3Client(bucketRegion);
            UploadFile(bucketName, keyName, filePath);
        }
    }
}

こちらはカスタムアクティビティとS3へのアップロードに必要なものです。

リスト5:AwsS3Activity(一部抜粋)

// for custom activity implementation
using System.Activities;
using System.ComponentModel;

// for AWS
using Amazon.S3;
using Amazon.S3.Transfer;
using System.IO;

UiPathのカスタムアクティビティで引数となるパラメータを、以下のように定義します。

リスト6:パラメータの定義

[Category("Input")]
[RequiredArgument]
public InArgument<string> BucketName { get; set; }

[Category("Input")]
[RequiredArgument]
public InArgument<string> KeyName { get; set; }

[Category("Input")]
[RequiredArgument]
public InArgument<string> FilePath { get; set; }

[Category("Input")]
[RequiredArgument]
public InArgument<string> AccessKey { get; set; }

[Category("Input")]
[RequiredArgument]
public InArgument<string> SecretKey { get; set; }

[Category("Input")]
[RequiredArgument]
public InArgument<Amazon.RegionEndpoint> BucketRegion { get; set; }

S3へファイルをアップロードするメソッドです。事前にインポートしているAWS関連のNuGetにあるUploadメソッドを使用します。

リスト7:アップロード用メソッド

private void UploadFile(string bucketName, string keyName, string filePath)
{
    try
    {
        var fileTransferUtility = new TransferUtility(s3Client);
        fileTransferUtility.Upload(filePath, bucketName, keyName);
    }
    catch (AmazonS3Exception e)
    {
        Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
        throw e;
    }
    catch (Exception e)
    {
        Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
        throw e;
    }
}

Executeメソッドは、カスタムアクティビティの実行時に呼ばれるものです。この中で、パラメータの読み取り、S3へのアップロードの処理(前述のUploadFileメソッドの呼び出し)を実装します。今回は出力の引数はありませんが、出力引数がある場合もこのメソッド内で実装しておきます。

リスト8:Executeメソッド

protected override void Execute(CodeActivityContext context)
{
    var bucketName = BucketName.Get(context);
    var keyName = KeyName.Get(context);
    var filePath = FilePath.Get(context);
    var accessKey = AccessKey.Get(context);
    var secretKey = SecretKey.Get(context);
    var bucketRegion = BucketRegion.Get(context);

    Amazon.Util.ProfileManager.RegisterProfile(profileName, accessKey, secretKey);
    s3Client = new AmazonS3Client(bucketRegion);
    UploadFile(bucketName, keyName, filePath);
}

以上で、今回のS3へファイルアップロードするカスタムアクティビティの実装は完了です。

単体テストも1ケースだけですが、下記のテストを実装しておきます。「UnitTestAwsS3Activity」プロジェクトに移動して、「UnitTest1.cs」にテストケースを実装します。「test.txt」というローカルのファイルを、このテストケースを使用してS3の「thinkit-test」バケットへ「custom_activity/uploaded_by_uip.txt」というキー名称でアップロードします。

リスト9:単体テストの実装

using Microsoft.VisualStudio.TestTools.UnitTesting;

using UiPathTeam.Aws.S3.Activities;
using System.Activities;
using System.Collections.Generic;

namespace UnitTestAwsS3Activity
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var activity = new AwsS3Activity();

            var input1 = new Dictionary<string, object>
            {
                { "BucketName", "thinkit-test" },
                { "KeyName", "custom_activity/uploaded_by_uip.txt" },
                { "FilePath", @"Z:\workspace\uipath\AwsS3Activity\UnitTestAwsS3Activity\data\test.txt" },
                { "AccessKey", "<Input Your AccessKey>" },
                { "SecretKey", "<Input Your SecretKey>" },
                { "BucketRegion", Amazon.RegionEndpoint.APNortheast1 },
            };

            var output1 = WorkflowInvoker.Invoke(activity, input1);
        }

    }
}

きわめてシンプルなテストコードですが、インプットは、Dictionary法で入力引数を渡し、カスタムアクティビティを実行します。今回は特にAssertで単体テストの結果検証をしておりませんが、ここでAssertを行うことでカスタムアクティビティの品質強化ができます。

Visual Studioにて、このテストコードを実行します。このコードが正しく稼働すれば、S3に「test.txt」がアップロードされているはずです。

S3のバケットにアクセスすると、指定したパラメータの通り「thinkit-test」バケットの「custom_activity」フォルダ内に「uploaded_by_uip.txt」というファイル名称でアップロードされていることが確認できます。単体テストとしては、この検証までを一気通貫で実装しておきたいところではありますが、一旦これで良しとしましょう。

アップロードされていることを確認

アップロードされていることを確認

動作検証ができましたので、このプロジェクトのビルドを実行してDLLを作成します。「AwsS3Activity」のプロジェクトにて、「Release」を選択し、「Build」を実行します。

DLLを作成

DLLを作成

UiPath株式会社
コーダーやプロジェクトマネージャーとして、金融、流通、飲食業界向けのシステム・ソフトウェア開発に従事し、2018年よりUiPath社に入社。RPAに関しては、過去にWeb画面、モバイル画面のUIテスト自動化、趣味では株式やFXのアービトラージにて活用していた経験あり。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています