UiPathプロセスの依存関係を抽出してみよう（Part３：依存関係解析編）

## はじめに

「Part2：Nupkg取得編」では、Ochestrator APIを用いてアクティブとなっているパッケージをローカルにダウンロードしました。今回は、ダウンロードされたNupkgを展開し、そのなかの`Project.json`からプロセスの依存関係を抽出する方法を説明いたします。まだPart1とPart2をご覧になっていない方は、以下のリンクで目を通しておきましょう。

https://qiita.com/Ouyang/items/51deb38d07ef190d2083

https://qiita.com/Ouyang/items/37ea16d87a305cd88b11

## 環境準備

| 項目 | バージョン |
|:-----------|------------:|
| UiPath Studio| 2024.10.6        |
| UiPath.WebAPI.Activities     | 1.21.1      |
| 対応OS     | Windows      |

## Nupkgの解凍

Nupkgファイルは、その拡張子を`zip`に変換すると解凍できます。`Project.json`ファイルを取得するために、解凍のワークフローを作成しておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/d94109c6-c5d5-4714-90b2-728003b1970e.png)

Part2でダウンロードしたNupkgファイルは、デスクトップ上の`Downloaded Nupkg`フォルダに保存されます。保存パスは`パッケージダウンロード.xaml`から引数として`パッケージ解凍.xaml`に渡すこともできますが、今回はワークフロー内で直接パスを指定する方法を採用します。

①代入アクティビティで以下の式を代入します。

```ruby:代入式
Dim stNupkgFolder As String
stNupkgFolder = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Downloaded Nupkg")
```

あわせて解凍先のフォルダも作成しましょう。

```ruby:代入式
Dim stUnzippedPackages As String
stUnzippedPackages = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Unzipped Packages")
```

ワークフローは以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/937306ee-4353-12bc-4498-5edcce099c58.png)

②フォルダの中のNupkgファイルを取得してループします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/9f1f42a5-a791-314a-810a-3a220730a7bf.png)

③本文でファイルの拡張子を`.zip`に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/6c4d15d9-40f8-fb00-6aa8-14c9cd03e3dc.png)

④ファイルを展開アクティビティで、変換されたzipファイルを上記作成した`Unzipped Packages`に展開します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/2fffb06e-dfd9-b8a5-2bfa-5d37b7be0c6f.png)

⑤ワークフローを実行して結果を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/07af1cb0-c72b-44c5-b37b-e47b454a5380.png)

## Project.jsonとは

そもそも`Project.json`ファイルとは何かを簡単に説明します。`Project.json`は、自動的に生成されるファイルで、プロジェクトフォルダー内のメインに設定されたxamlファイルに関連付けられます。このファイルには、プロジェクトの依存関係や読み込まれたWebサービスなど、さまざまな情報が記載されています。詳細については、公式ドキュメントをご参照ください。

https://docs.uipath.com/ja/studio/standalone/2024.10/user-guide/about-the-projectjson-file

では、`Office365_Work_1.0.3`というプロセスを例にして、その`Project.json`ファイルの格納場所と依存関係の記載方法を確認しましょう。

①格納場所

Windowsプロジェクトの場合、`Project.json`は、`Packageフォルダ\content`に入っています。

Windowsレガシの場合、`Project.json`は、`Packageフォルダ\lib\net45`に入っています。

今回の処理対象はすべてWindowsプロジェクトです。

②依存関係の記載方法

`Project.json`を右クリックし、メモ帳（Notepad++でも可）で開いたら、依存関係は下記赤枠のように記載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/5f3fe668-a785-e716-3721-8ea80a9608b7.png)

今回は、その情報の抽出を目標としています。

## 依存関係の抽出

いよいよここまでたどり着きました。`依存関係抽出器.xaml`を作成してワークフローを組み立てましょう。

①データテーブルを構築して抽出情報をこちらに格納する準備をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/bb5d75ac-ce51-a178-e6a8-64aa378223b8.png)

②`Unzipped Packages`中のプロセスフォルダをループして`Project.json`を取得します。

具体的なコードは以下の通りです。

```ruby:コード
'Unzipped Packages中のパッケージフォルダをすべて取得します
Dim arrPackagePath() As String
arrPackagePath=System.IO.Directory.GetDirectories(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Unzipped Packages"))
'Unzipped Packages中のパッケージフォルダをループします
For Each package As String In arrPackagePath
    '各パッケージの名前を取得します
    Dim stPackageName As String = System.IO.Path.GetFileName(package)
    '各パッケージフォルダの中のProject.jsonを探します
    Dim arrProjectJson As String() = System.IO.Directory.GetFiles(package & "\content","project.json")
    For Each jsonfile As String In arrProjectJson
        本文
    Next
Next
```

以上のコードを用いて組み立てたワークフローは以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/08a8f355-e231-8280-221c-0f44ebbcbe24.png)

③本文で、`Project.json`をテキストファイルとして読み込み、逆シリアルしてJobject型に整形します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/ce2f6f25-a18e-afe6-e284-c309bd976d87.png)

④`jsObject`変数は`Project.json`の中身を逆シリアル化してJObject型に整形した結果です。この変数には、dependenciesキーが存在するはずですが、万が一存在しない場合にエラーが発生する可能性があります。そのため、念のためにIF分岐で確認しましょう。dependenciesキーが存在する場合は、それを利用して依存関係を抽出します。一方、存在しない場合はループをスキップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/fce1206a-66ac-e6ed-44ee-87ed6d4d0012.png)

⑤キーが存在する場合は、緑枠（Sequence/DepAnalyzer）を展開して、依存関係を抽出します。抽出する前に、もう一度依存関係の構造を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/f6057279-013c-2675-f673-f6b0368808cd.png)

まずは、Valueを取得します。

```ruby:コード
Dim stAllDeps As String = jsObject("dependencies").ToString
```

そうすると、以下の部分が取得できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/d0e8e780-4f38-7f6a-7dee-5be18df2b9b1.png)

次に、アイエの順で、それぞれ、コンマ、コロン、ダブルコーテーションを分離して、一行一依存関係で情報を整理します。。

ア、コンマで各行の依存関係を分離してループします。

```ruby:コード
Dim arrAllDeps() As String = stAllDeps.Split(","c)
For Each partDep in arrAllDeps
  本文
Next
```

イ、本文の中で、コロンを区切り文字にして依存関係名と依存関係のバージョンを分離します。続いてダブルコーテーションと改行コードを消去して、依存関係名と依存関係のバージョンを抽出します（エ）。

```ruby:上記コードの本文
Dim arrPartDep() As String = partDep.Split(":"c)
Dim stDepName As String = arrPartDep(0).Replace("""","").Replace("{","").Replace(vbCrLf & vbCrLf, vbCrLf).Trim()
Dim stDepVer As String = arrPartDep(1).Replace("""","").Replace("}","").Replace(vbCrLf & vbCrLf, vbCrLf).Trim()
```

最後に、パッケージ名、依存関係名、依存関係バージョンをデータテーブルに追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/c041f0f5-92e8-5431-6ab3-c42a1b87b9a2.png)

以上の手順を参照して作成した緑枠(Sequence/DepAnalyzer)は以下の通りになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/eb2d060d-5e7c-1f51-d21c-21c39c1a2833.png)

⑥データテーブルをExcelファイルを書き込みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/c998ba71-a837-8407-e384-75239bb94a53.png)

## 終わりに

それでは、実行して結果を見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3334103/c5fcc1e8-82ab-d951-25c3-8ce8e633f649.png)

依存関係が正しく抽出できましたね。長いですが、以上がUiPathプロセスの依存関係を抽出する方法でした。それほど頻繫に変わらない情報なので、月に一回ほど、抽出すればよいでしょう。

番外の予告ですが、最近Autopilot For Everyoneが流行っているため、それを利用して依存関係が取得できればいいなという発想で「UiPathプロセスの依存関係を抽出してみよう（番外編：Autopilot for everyoneで遊んでみた）」を執筆しようと思っております！楽しみにしてください。