この記事の要約
- UiPathのプロセス終了時に、PiPセッションを自動終了する方法の説明
- アイデア
-
Invoke PowerShell
アクティビティでshutdown.exe /l
を実行 -> PiPセッションからサインアウト - カレントセッションがPiPセッションか否かを
quser.exe
で判定
-
Picture in Picture機能とは
Picture in Picture(以降PiP)は、UiPath v2020.4で追加されたAttended Robot用の機能で、
Robotを別ウィンドウ上の別セッション(PiPセッション)上で実行させることができる便利な機能です。
ピクチャ イン ピクチャ
https://docs.uipath.com/robot/lang-ja/docs/picture-in-picture
PiPセッションはユーザーの画面・セッションとは独立しているため、以下のようにRobotを安定して実行させることができるようになります。
- ユーザーのマウス・キーボード操作によるRobotの妨害・誤動作を防げる
- Robot実行中でも他の作業をできる
- ユーザーがスクリーンロックしてもRobotが実行を継続できる
- マウスクリックなどの一部のアクティビティは、スクリーンロック中は動かない
ただし、PiPにもいくつかの制限事項があり、ちょっと厄介なのが下記2点。
- PiP セッションを事前に閉じる必要があるため、PiP セッションが開いている間はマシンを再起動またはシャットダウンできません。
- 一度に開始できるピクチャ イン ピクチャ セッションは 1 つのみです。
Attended Robotを共有PCで運用している場合、あるユーザーが実行してPiPセッションを開いたまま放置していると、他のユーザーが使うことができなくなってしまいます。また、PCの再起動・シャットダウンもできなくなると、Windows Updateも滞ってしまい、共有PCの運用に支障が出てしまいます。
PiPセッションを自動終了させる方法
UiPathのプロセス終了時にPiPセッションも自動終了してくれると嬉しいのですが、残念なことに v2020.10 時点ではそのような機能はありません。
なので、作ってしまいましょう。
基本的なアイデア
PiPセッションは、PiPセッションからサインアウトすることで終了させることができます(PiPウィンドウも自動で閉じます)。
サインアウトはスタートボタンからだけでなく、shutdown.exe /l
をコマンドライン実行することでも行えるので、基本的なアイデアはInvoke PowerShell
アクティビティでshutdown.exe /l
を実行することになります。
ただし、UiPathのプロセス内でサインアウト処理を行ってしまうと、Robotが外部から強制終了されて異常終了の扱いになってしまうため、shutdown.exe
をRobotとは別プロセスで実行するようにします。やり方は下記の通り。
Start-Process -FilePath shutdown.exe -ArgumentList '/l'
Robot終了直前にいきなりサインアウトが走るのは少し怖いので、例えば5秒待ってからサインアウトするときは下記のようにStart-Sleep 5
を挟みます。
Start-Process -FilePath powershell.exe -WindowStyle Hidden -ArgumentList '-Command Start-Sleep 5; shutdown.exe /l'
ワークフローやシーケンスの最後で上記PowerShellスクリプトをInvoke PowerShell
アクティビティで実行するだけで、「PiPセッションを自動終了させる」という当初の目的は概ね達成できます。
しかし、開発・テストの都合でPiP機能を使わずにプロセスを実行した場合にもサインアウトが走ってしまうという問題があります。
カレントセッションがPiPセッションか否かを判定する
PiPセッションの場合だけshutdown.exe /l
を実行させるようにするために、カレントセッションがPiPセッションか否かを判別する方法を考えます。
幸い、環境変数%SESSIONNAME%
の値によって、カレントセッションがPiPセッションか否かをある程度判断できます。
%SESSIONNAME%
を取得するにはquser.exe
を使います1。
PS C:\> quser.exe
USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME
takeruko console 1 Active . 3/4/2021 09:31
takeruko rdp-tcp#16 8 Active . 3/4/2021 09:47
>takeruko 7a78855482a0... 14 Active . 3/4/2021 12:56
quser.exe
を実行すると、PC上の全てのセッションが一覧表示されます。
行の先頭に>
が付いているID:14
がカレントセッションです。
SESSIONNAME
の値はセッションの接続方法によって以下のような値を取るようです。
SESSIONNAMEの値 | セッションの種類/接続方法 |
---|---|
console | ローカルからサインイン |
rdp-tcp#... | リモートデスクトップ接続 |
上記以外 | PiPセッションなど |
今回はカレントセッションがユーザーセッション(ローカルからのサインインやリモートデスクトップ接続)ではない事が判別できればいいので、以下のようなPowershellスクリプトを実行します。
# quser.exeは%windir%¥Sysnative 配下
$quser = $env:windir + '\Sysnative\quser.exe'
$csv = . $quser | ForEach-Object -Process { $_ -replace '\s{2,}',',' } | ConvertFrom-Csv
foreach ($row in $csv) {
if ( $row.USERNAME.StartsWith('>') -and $row.SESSIONNAME -notmatch '(console|rdp-tcp#.+)' ) {
Start-Process -FilePath powershell.exe -WindowStyle Hidden -ArgumentList '-Command Start-Sleep 5; shutdown.exe /l'
}
}
後は、上記スクリプトをInvoke PowerShell
アクティビティのコマンドテキストに貼り付けて、TypeArgumentをString
、スクリプト入力にチェックを入れればOKです。
以上
-
Get Environment Variable
アクティビティとかで%SESSIONNAME%
を直接取得できると楽なんですが、UiPathのRobotは仕組み上一部の環境変数を取得できない模様。 ↩