クロスプラットフォームのプロジェクトでLinux環境のロボットからマシン上のコマンドを実行する

注記: 本稿は `registry.uipath.com/robot/uiautomation-runtime:23.4.61.49114-robot23.4.2` のDockerコンテナ、2023/07/22時点リリース済みのUiPath、及びアクティビティを使用して検証を行ったもので、将来のバージョンでも同様の動作となることを保証するものではありません。

## はじめに
UiPathは[2年ほど前からLinux環境（docker）でのロボットの実行をサポート](https://docs.uipath.com/ja/robot/standalone/2021.10/user-guide/release-notes-2021-10-3#linux-robots
)しています。

ロボットがLinux上で動作するため、制約としてクロスプラットフォームのプロジェクトのみの対応となり、使用できるアクティビティが限定されます。

アクティビティの各プロジェクトへの対応状況はガイドに記載されています。
例えば[UiPath.UIAutomation.Activitiesのモダンアクティビティ](https://docs.uipath.com/ja/activities/other/latest/ui-automation/uia-modern-project-compatibility)については2023/07/22時点で次のようになっています。
アクティビティパッケージによっては、各アクティビティについて対応・非対応が混在していることにご注意ください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/cb4f4943-4f4f-7897-bba9-5eb2d17c9e16.png)


UIAutomation以外のものとしては例えばIntegration Serviceのアクティビティはクロスプラットフォームのプロジェクトに対応しています。その他では『HTTP 要求』のようなアクティビティも使えるため、制限はあるもののニーズを満たせる場面は少なくないのではないかと思います。

この記事では更にもうワンステップできることを広げる方法として、Linux環境のロボットからマシン上のコマンドを実行する方法をご紹介します。

## ワークフロー実装
例として `hostname` コマンドを実行してその結果をログに書き込むワークフローを用意しました。
方法は凄くシンプルで、System.DiagnosticsのProcessクラスを使って対象のコマンドを実行するだけです。

参考:
「System.Diagnostics > Process クラス」
https://learn.microsoft.com/ja-jp/dotnet/api/system.diagnostics.process

### 全体
全部でアクティビティが5個で、重要なのは『コードを呼び出し』のみです。シンプルですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/d501629e-8d75-6163-b593-cadf51a9990c.png)

### 解説
まずcommand変数に `hostname` を割り当てます。
`hostname` は端末のマシン名を出力するだけのコマンドです。
他のコマンドを試してみるときに、もしパスが通っておらずコマンドが見つからない等のエラーが出るときはそのコマンドへのフルパスを指定しましょう。

次にarguments変数ですが、今回は引数は使用しないため空のListを作成して割り当てています。
コマンドに引数を与えたい場合はここで指定を行います。
その際は例えば次のように初期化子（`{` と `}` で囲まれた部分）を追加してインスタンスを作成しましょう。

```csharp
New List(Of String) {"引数1", "引数2"}
```

『コードを呼び出し』アクティビティのコードは次の内容です。
```csharp
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.FileName = command;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = true;
foreach (var arg in arguments) {
    processInfo.ArgumentList.Add(arg);
}
Process process = Process.Start(processInfo);
stdout = process.StandardOutput.ReadToEnd();
process.WaitForExit();
result = process.ExitCode;
```

パラメーターは次の内容です。

commandで実行対象のコマンド、argumentsとしてコマンドに与える引数を指定します。
resultとしてプロセスの終了コード、stdoutとしてプロセスからの標準出力を取得します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/57824cb4-3c78-8406-f793-1154d1e8eafc.png)

今回は実装していませんが、必要があればstderr等についても実装を追加しましょう。

## Orchestratorの設定
### マシンテンプレートを作成します
Linux環境のロボットであっても特別な設定は必要ありません。
マシンテンプレートを作成し、Unattended ランタイムを1つ割り当てます。
作成後にクライアントIDとシークレットをメモしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/65442630-cbb6-9060-a237-a3f141cb9294.png)

### フォルダへのマシンテンプレートの割り当て
前の手順で作成したマシンテンプレートをフォルダに割り当てます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/c057f0b0-3470-4a49-efe5-42869642eba2.png)

### フォルダへのユーザーの割り当て
Unattendedロボットが実行できるユーザーをフォルダへ割り当てる必要があります。
Automation Userの権限を付与します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/b7e80d08-6d2e-5cfc-29e4-0f7cca34fdf0.png)

ユーザーの割り当てを忘れると次のエラーが発生し、ジョブの作成ができません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/172794e0-6bd6-ae3d-424c-2f2430716d6f.png)

## Dockerの設定
次のコマンドでLinuxコンテナを起動します。
クライアントIDとシークレットは以前の手順でメモしておいたものです。

```
docker run -e LICENSE_AGREEMENT=accept -e ORCHESTRATOR_URL="オーケストレーターのURL" -e CLIENT_ID="クライアントID" -e CLIENT_SECRET="シークレット" -p 50000:5900 --env VNC_ENABLED=true registry.uipath.com/robot/uiautomation-runtime:23.4.61.49114-robot23.4.2
```

注: latestタグが存在しないのか、2023/07/22時点では明示的にtag（23.4.61.49114-robot23.4.2）を指定しないとうまくいきませんでした。

起動したLinuxコンテナがOrchestratorへHTTPSで通信ができることが必須です。
またプロジェクトの依存パッケージをダウンロードするため、パッケージフィードへの通信も必要になります。

参考:
「Robot > Linux Robots - Standalone 2023.4」
https://docs.uipath.com/ja/robot/standalone/2023.4/user-guide/linux-robots

## ジョブの実行

パブリッシュしたプロセスを指定してジョブを作成し、実行します。
必要があればAccountやMachineを明示的に指定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/2b1140ce-6fc8-cac3-4d3c-4faa9f2e8522.png)

実行されたジョブのログは次のようになり、期待した通りLinuxコンテナのホスト名が出力されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331558/d302dc82-93e0-3103-1d77-f37eab8abbf7.png)


## おわりに
クロスプラットフォームのプロジェクトではアクティビティの対応状況により、できることにやや制限がありますが、一方でWindowsとは異なるOS上でロボットを実行できるという利点もあります。
Linuxがサポートする多彩なコマンドが使用できることが強みになる場面も当然ながら存在するはずです。
そのようなシーンを開拓する際にこの記事が参考になりましたら幸いです。