【UiPath】タイムトリガーを次回実行順で表示する

この投稿は「UiPath Advent Calendar 2024」の5日目のエントリです。

https://qiita.com/advent-calendar/2024/uipath

# 何をするか

この件です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/6fc6e3c6-8cd0-9980-9399-1f26f8f0df9d.png)

2024年12月時点の「Cloud Orchestrator」では、 `タイムトリガーを「次回実行時間順」で並び替え／ソートできない` ので、「次に実行されるタイムトリガーは何だろう？」と思ったときに、目で見て把握する必要があります。

ですが、目で見て把握するのは厳しい。トリガーが増えて複数ページになったら、かなり面倒で苛立ちます。なぜソートできないのか！

## なぜ「次回実行時間順」にソート機能が無いのか？
（あくまで推測ですが） Orchestratorのタイムトリガーの登録内容を見ると、Cron式で1回限りの実行でない限り「次回実行時間」を持っていません。登録したデータは「繰り返し実行のルール」があるだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/482d18fb-b5ef-bf9a-d108-bfc6a39f9484.png)

つまり、次回実行時間は「登録内容と現在日時を加味して計算した参考値」でなので、SQL実行時には「並び替えのキーに指定しにくい（できるけど「都度計算で結果が変わる」のでキャッシュが有効活用できず、クエリ実行時のコストになってしまう）」のだと思います。

とすると、今後、ソート項目に足されるのは厳しいかもしれない。（足してほしいけれど）

# どうするか？
（APIで）ある程度絞ってデータを取得して、並び替えれば出来ます。
Xamlで書いても良いし、Powerautomateでも良いですが、処理の内容が説明しやすいように「PowerShell」で作ってみます。

# コードサンプル：各種設定
まずは、API実行のための「トークン」を取得です。AutomationCloud にログインし、「PrivateAccessToken」を発行します。
　`場所）AutomationCloud > 右上ユーザーアイコンを右クリック > 設定 > 個人用アクセストークン`

今回はタイムトリガーの情報を取得するので、必要な権限は「OrchestratorAPIAccess」の「Jobs.Read」です。取得したトークンを、以下でセットします。
``` bat
# トークン
$token = 'rt_・・・・・・'
```
次にAPIのベースURLを確認します。
Orchestratorのテナントの情報になるので、以下の例に倣ってOrchestratorのURLの前方の情報をセットします。
　`例）https://cloud.uipath.com/{個別のID}/{テナント名}/orchestrator_/`
``` bat
# URL
$baseUrl = 'https://cloud.uipath.com/{個別のID}/{テナント名}'
```
次は取得対象のフォルダの指定です。
OrchestratorのAPIは基本的に「フォルダ単位でしか処理ができない」ので、トリガーデータの取得もフォルダ単位で分割して行います。
PowerShellの変数にフォルダの「名前」と「ID」を以下のようにセットします。
（フォルダIDは、OrchestratorのURLで「fid=******」となっている部分から把握できます）
今回は、実行結果を分かりやすくするために「フォルダ名」も一緒にセットしています。

``` bat
# フォルダ
$ary_folder = @()
$ary_folder += New-Object PSObject -Property @{Id = "6127328"; Name = "管理部"}
$ary_folder += New-Object PSObject -Property @{Id = "6127329"; Name = "マーケ部"}
```
最後に結果の出力先ファイルパスを指定します。
``` bat
# 出力ファイルパス
$outputPath = "C:\work\nexttrigger_" + (Get-Date -Format "yyyy-MMdd-HHmmss") + ".txt"
```

# コードサンプル：データの取得
続いて APIからデータを取得します。
以下でタイムトリガーの情報を「API：ProcessSchedules」から「有効」になっているデータに絞り込んで取得します。

``` bat
# トリガー情報取得
$ary_trigger = @()
$url = $baseUrl + '/orchestrator_/odata/ProcessSchedules?$filter=Enabled%20eq%20true'# 有効のみ
foreach($folder in $ary_folder){
    $headers = @{"Authorization" = "Bearer " + $token; "X-UIPATH-OrganizationUnitId" = $folder.id}
    $response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers -ContentType "application/json"
    if ($response.StatusCode -lt 300){
        foreach($dat in $response.value){
            $MachineName = ""
            if($dat.MachineRobots -ne $null){
                $MachineName =$dat.MachineRobots.MachineName
            }
            $NextOccurrence = ""
            $NextDate = ""
            if($dat.StartProcessNextOccurrence -ne $null){
                $NextOccurrence = (Get-Date -Date $dat.StartProcessNextOccurrence).ToString("yyyy/MM/dd HH:mm:00")
                $NextDate = (Get-Date -Date $dat.StartProcessNextOccurrence).ToString("yyyy/MM/dd")
            }
            $item = New-Object PSObject -Property @{
                Name = $dat.Name
                MachineName = $MachineName
                UnitName = $folder.Name
                StartTime = $NextOccurrence
                StartDate = $NextDate               
            }
            $ary_trigger += $item
        }
    }else{
         Write-Host $response.StatusCode
         Write-Host $response.StatusDescription
         throw ”API呼び出しエラー”
    }
    Write-Host "[Get]Sleep - 5 Seconds...(optional　delay　for api rate limit)"
    Sleep 5
}
```

# コードサンプル：データの絞り込み・並び替え・出力
取得後に「次回実行が本日」に絞り込み「実行開始順」で並び替えて出力します。
``` bat
# 絞り込み・並び替え
$ary_trigger = $ary_trigger | Where-Object StartDate　-eq (Get-Date -Format "yyyy/MM/dd")
$ary_trigger = $ary_trigger | Select-Object StartTime, MachineName, UnitName, Name
$ary_trigger = $ary_trigger | Sort-Object -Property StartTime, Name
# 結果出力：CSV
$ary_trigger | Export-Csv $outputPath -Encoding Default
```

説明は以上です。
全て繋げると以下のようになります。
``` bat
# トークン
$token = 'rt_・・・・・・'

# URL
$baseUrl = 'https://cloud.uipath.com/{個別のID}/{テナント名}'

# フォルダ
$ary_folder = @()
$ary_folder += New-Object PSObject -Property @{Id = "6127328"; Name = "管理部"}
$ary_folder += New-Object PSObject -Property @{Id = "6127329"; Name = "マーケ部"}

# 出力ファイルパス
$outputPath = "C:\work\nexttrigger_" + (Get-Date -Format "yyyy-MMdd-HHmmss") + ".txt"

# トリガー情報取得
$ary_trigger = @()
$url = $baseUrl + '/orchestrator_/odata/ProcessSchedules?$filter=Enabled%20eq%20true'# 有効のみ
foreach($folder in $ary_folder){
    $headers = @{"Authorization" = "Bearer " + $token; "X-UIPATH-OrganizationUnitId" = $folder.id}
    $response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers -ContentType "application/json"
    if ($response.StatusCode -lt 300){
        foreach($dat in $response.value){
            $MachineName = ""
            if($dat.MachineRobots -ne $null){
                $MachineName =$dat.MachineRobots.MachineName
            }
            $NextOccurrence = ""
            $NextDate = ""
            if($dat.StartProcessNextOccurrence -ne $null){
                $NextOccurrence = (Get-Date -Date $dat.StartProcessNextOccurrence).ToString("yyyy/MM/dd HH:mm:00")
                $NextDate = (Get-Date -Date $dat.StartProcessNextOccurrence).ToString("yyyy/MM/dd")
            }
            $item = New-Object PSObject -Property @{
                Name = $dat.Name
                MachineName = $MachineName
                UnitName = $folder.Name
                StartTime = $NextOccurrence
                StartDate = $NextDate               
            }
            $ary_trigger += $item
        }
    }else{
         Write-Host $response.StatusCode
         Write-Host $response.StatusDescription
         throw ”API呼び出しエラー”
    }
    Write-Host "[Get]Sleep - 5 Seconds...(optional　delay　for api rate limit)"
    Sleep 5
}

# 絞り込み・並び替え
$ary_trigger = $ary_trigger | Where-Object StartDate　-eq (Get-Date -Format "yyyy/MM/dd")
$ary_trigger = $ary_trigger | Select-Object StartTime, MachineName, UnitName, Name
$ary_trigger = $ary_trigger | Sort-Object -Property StartTime, Name

# 結果出力：CSV
$ary_trigger | Export-Csv $outputPath -Encoding Default
$ary_trigger | Format-Table
```

# 実行結果・出力内容
上記のコードを実行すると、画面上に結果が整形して表示され、指定の出力先にCSVファイルが出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/89494753-544f-f269-4a8f-594f164ff217.png)

次回実行を知りたい時に実行でも、タスクスケジューラーに登録＆SlackやTeamsに投稿機能をつけて、定期実行させても良いかもしれません。

# 終わりに
以上、タイムトリガーをAPIで取得する 方法の紹介でした。