皆もすなるQiitaといふものを、儂もしてみむとてするなり。
と言う訳で、こん**は!はなっち!です。
この記事はUiPathブログ発信チャレンジ2023サマーの3日目の記事です。
【初めに】
お客様から貸与されたパソコン。無論セキュリティレベルは高く、検索して出てきたリンク先が制限が掛かったりすると、ガッカリしてしまう。
仕方なく、個人ネットワークに接続した自前のパソコンを使って、その制限が掛かっているサイトを見て、あぁ、この情報なら知っていたと思ってガッカリしてしまう。
まぁ、自分なりの考えでやってみよう!と気を取り直してお客様から貸与されたパソコンに向かうと、スクリーンセーバーが働いていて、そこから復帰するのにログインIDとパスワードを入力して...と意外と手間、そのストレス...
マウスが動いていればスクリーンセーバーが働かず、復帰するための再度ログインする操作は不要となる。ならば、マウスを動かし続けるロボットを作ってしまえ!
今回は、単にマウスを動かし続けるロボットを作った!だけでは面白くないので、どのようにロボットを成長させたかも併せて書こうと思います。
1 マウスは動かせるのか。
ロボットがマウスを動かす事が出来なければ、意味はありません。
まずは、「ホバー」アクティビティを使って、ロボットがマウスを動かせるか確認しました。
ターゲット要素は特定せず、カーソルの位置を(X,Y)=(200,400)にしてみます。
実行してみましょう。
ちゃんと移動しました。
2 マウスを動かし続ける。
マウスを動かす事はできました。ただ、これは一回だけなので、複数回動かすように改造します。
2-1 移動させる座標を決める。
最初のカーソルの位置は(X,Y)=(200,400)としました。次は (X,Y)=(X+α,Y+α) α=1 とすると、いずれは画面サイズを超えたところにカーソル位置を持っていくことになります。
スクリーンセーバーが起動されなければ、カーソル位置を常に新しい場所にする必要はなく、最低2点あれば十分ですので。int32型配列として保持する事にしました。
2-2 繰り返し回数を決める。
スクリーンセーバーが起動する時間に到達する以前に、マウスを動かします。例えば5分だとしたら、4分毎に動かし、2回目の8分後にスクリーンセーバーが動いていなければ、大成功です。
繰り返し回数を決めたら、「繰り返し (コレクションの各要素)」アクティビティを配置し、その中に、「ホバー」アクティビティを配します。例では3回としています。
繰り返し:currentItem(Object型)
次のコレクションの要素:Enumerable.range(0,3)

カーソルの位置は、先の図のように、変数Xと変数Yを宣言、定義してあるので、それを利用します。
繰り返しで指定した変数を利用すると、要素2の配列に対して3回目の繰り返しの際に、配列の範囲外の例外を起こしてしまいます。ですので、剰余(mod)を使って、配列外の参照が行われないようにします。
Xのオフセット:X(CInt(currentItem.ToString) mod X.Count)
Yのオフセット:Y(CInt(currentItem.ToString) mod Y.Count)

2-3 繰り返し間隔を決める。
このままですと、 「ホバー」アクティビティが実行した直後に再び 「ホバー」アクティビティを実行してしまい、忙しないマウス操作になってしまいます。 「ホバー」アクティビティにも「実行後の待機時間」パラメタがありますので、それを活用します。例では、60000ミリ秒で、つまり1分です。
実行後の待機時間:60000

こうする事で、「3回の繰り返し=3分」 と言う事になります。
3 処理が終わったあとの処理を決める。
「繰り返し (コレクションの各要素)」アクティビティで指定回数、「ホバー」アクティビティでマウスを動かし終わったら、当然その処理は終了します。それを気が付かずにまたスクリーンセーバーが起動して、使おうと思ったログインする操作を...これでは元も子もありません。
3-1 音で終了を報せる。
ここでは、「警告音」アクティビティを使って、サウンドを鳴らすようにしましょう。一回では心もとないので、「繰り返し (コレクションの各要素)」アクティビティで3回鳴らすようにします。ただ、「警告音」アクティビティが連続して実行されても、一回目のサウンドが鳴り終わるまで、次のサウンドはなりません。ですので、「Delay」アクティビティを入れています。
4 汎用的に使えるように処理を決める。
「ホバー」アクティビティを繰返して処理させる回数は、固定にしていました。例えば、ちょっと銀行へ行って帰ってくる30分、マウスを動かし続けてほしいなぁ。なんて時に、ロボットを修正
するとか、CONFIGファイル
を用意して…なんて事は非常にまだるっこしいですね。
Attendedライセンスの場合、長時間の離席での運用を想定していません。記事の中でのお話です。
4-1 固定数のホバー処理を可変にする。
固定で決めていた値は、変数を宣言、定義しての大丈夫です。そこに都度値を代入してあげ、それを参照してあげれば、汎用的になります。
その変数にどのようにして値を渡すか...
そういう時は、「入力ダイアログ」アクティビティの出番です。
実行すると、以下ののような画面が出てきて、入力を促されます。入力した値は、String型変数に格納されるので、未入力であったり、Int32型変数に変換した時のエラーの際は処理しないように制御できますね。
4-2 ホバー処理を回数入力ではなく、○時○分までとする。
現在の時刻(9時20分)から、午後2時45分からの打合せの時間まで、5時間25分あるから、5(時間)*60(分)+25(分)=325(分)を入力すればいいや。。。でも毎回こんな計算するの大変だよなぁ。。。だったら、先の 「入力ダイアログ」アクティビティにホバー処理を終了させる時刻、例えば「13:45」と入れて、現在の時刻から分単位の差分を取ればいいか!
となると、「入力ダイアログ」アクティビティに入力される値を想定し、
-
数値
... これはそのまま繰り返し回数とする。 -
HH:mm
... これは繰り返し終了までの時刻とする。 -
上記以外
... 想定していない入力なので、この時点で処理終了とする。
数値
かどうかを判断してからInt32型の変数に入れるというような二段階ではなく、数値
をInt32型に変換して、エラーでなければ数値
、エラーだったら、HH:mm
の入力なのかもしれないと考え、ここでは、「Try~Catch」アクティビティを利用します。
- SECOND 代入 `←表示名がちがっていますね`
Minute ← CINT(INPUTVALUE)
もしExceptionが発生したら、数値
ではなく、HH:mm
が入力された処理を行います。
- NOWTIMESPAN 代入
NOWTIMESPAN ← New TimeSpan(now.Hour, now.Minute,0)
- INPUTTIMESPAN 代入
INPUTTIMESPAN ← New TimeSpan(CINT(INPUTVALUE.split(":"c)(0)), CINT(INPUTVALUE.split(":"c)(1)), 0)
- Minute 代入
Minute ← CINT(INPUTTIMESPAN.Subtract(NOWTIMESPAN).TotalMinutes)
ちょっと汚いやり方ですが、INPUTTIMESPANを代入する際、 「入力ダイアログ」アクティビティから入力された値を、コロン(:)でSplitし、その配列(0)がHH:mm
の時部分、その配列(1)がHH:mm
の分部分、秒は0としてTimeSpanを求めています。
入力したTimeSpan値から、現在のTimeSpan値を減じたTimeSpan値の総分数を得るのに、.TotalMinutesメソッドを使っています。
【まとめ】
・ホバーを繰返すことで、目的とする機能が実現出来たら、前後左右に機能を考えてみる事が、ロボット開発の醍醐味です。
・ロボットの内容に、正解はありません。あらゆる手法で目的とする機能が出来たら、それが正解です。いろいろと試行錯誤してましょう。
##おわりに
いかがでした?
今回も読んでいただきありがとうございました!
是非UiPathでのロボ開発の一助になればと思っています。
ありがとうございました!