こんにちは。入社2年目の小玉です。
GMOインターネットグループ横断で2021年から取り組んでいる「RPA・AI・ロボット・動画活用No.1グループへ」のプロジェクトに携わっており、RPAで業務自動化できるものが幾つもあったので、ご紹介いたします。
1. RPA とは
定義は「ロボットによる業務自動化」のことを指します。
総務省からの言葉を引用すると「人間が行ってきた定型的なパソコン操作をソフトウエアのロボットにより自動化するもの」です。
これは、単にRPAツールと呼ばれているものだけを指すとは限らないことに注意してください。例えば、Shellスクリプトなどでの自動化もRPAに含まれます。また、それぞれのRPAツール、プログラミングでの開発には、メリット・デメリットが存在します。詳しく見ていきましょう。
2. RPA ツール比較
私が、実際に業務で使用したものの一部を例にそれぞれのRPAツールのメリット・デメリットをご説明します。
Power Automate Desktop
メリット デメリット ノーコードでの開発 無料スケジューリングが複雑 インターネット上の情報が豊富 逐次処理のみ Desktop、Web Appの自動化 gitバージョン管理が困難 画像処理、OCR Windowsのみのサポート
Power Automate Desktopメリットは、やはり「ノーコード」です。
WindowsのデスクトップアプリやブラウザからアクセスできるWebアプリなどほとんどのアプリケーションを「ノーコード」で自動化することができます。特にExcel操作などは非常に得意です。
また、画像処理などができる点も便利です。簡単に画像にマウスを移動させたり、画像の存在確認などで条件分岐を行ったりすることができます。
デメリットは、無料アカウントの場合、スケジューリングがやや難しいということです。
Power Automate Desktopには、無料アカウントと有料アカウントがあり、有料アカウントの場合は、Web版のPower Automateから簡単にスケジューリングが可能です。しかし、無料アカウントの場合は、後述する「UIAutomation」ライブラリとタスクスケジューラーを用いて、スケジューリングしなければなりません。
続いて、Power ShellやBatch Fileを使って自動化するメリット・デメリットを見てみましょう。
Power Shell, Batch File
メリット デメリット Windows API直接操作 学習コストが発生 実行が非常に簡単 Power Shell版の「UIAutomation」ライブラリの情報の少なさ並行で実行可能 VB、C#との高い親和性 タスクスケジューラーでの実行
Power Shell, Batch Fileのメリットは、「実行が非常に簡単」ということです。
特にBatch Fileは、ファイルのパスを指定するだけで、コマンドプロンプトなどからすぐに実行できますし、タスクスケジューラーでもパスを指定するだけでスケジューリングできます。また、簡単なC#やVBプログラムを埋め込んだり、その他のプログラミング言語でも簡単に実行できます。
デメリットは学習コストが発生することです。
また、UI要素を操作することができるPower Shell版の「UIAutomation」ライブラリのインターネット上の情報が少ないこともデメリットです。
SikuliX
メリット デメリット 画像処理の実装が簡単 python3系のサポート対象外(現在開発中)学習コストがほぼゼロ javaをインストールが必須実行が簡単 python(2.7)が使用可能 マルチプラットフォーム対応
SikuliXは、画像認識を利用したUI操作自動化ツールで主に視覚情報からマウスのイベントを発生させるというフローを自動化することができます。
SikuliXのメリットは、「マルチプラットフォーム」です。
Windowsだけではなく、MacやUbuntuなどに対応しています。また、Jython、Python、Rubyなどのプログラムを使用することができ、Mavenで依存関係を追加して、Javaから「SikuliX API」を使用することができると公式に書いてあります。
デメリットは「python3」に対応していないことです。
VB, C#, Go, python, C++などのプログラミング言語を使った自動化
メリット デメリットWindows APIや機械学習など高い学習コストRPAツールより高度な実装が可能 膨大な開発時間環境の依存しにくさ開発できるのがエンジニアのみ
メリットは「高度なことが実装できる」ということです。
デメリットは、「学習コストが高い」ということです。自動化する対象の業務が、RPAツールで対応できない場合は、プログラミング言語を用いて開発するとよいでしょう。
Power Automate/ DesktopPower Shell/ Batch FileSikuliXプログラミング言語を使った自動化メリットノーコード情報が豊富実行が簡単/VB,C#との高い親和性画像処理系が簡単/マルチプラットフォーム高度な実装が可能デメリット無料アカウントはスケジューリングが困難UIAutomationの情報量の少なさJavaのインストールが必須高い学習コスト/開発できるのがエンジニアのみ
このようにそれぞれのRPAツールにメリット・デメリットが存在します。自動化対象の業務に合わせて、ツールも変えていきましょう。それでは、それぞれのツールを使った自動化の具体例を見てみましょう。
3. Power Automate Desktop を使った自動化の例
簡単な例として「Chromeを起動して、ボタンを押す」作業をPower Automate Desktop(PADとも略されます)で実装してみましょう。フロー作成手順は以下の通りです。この記事は、Windows Server 2019で動作しています。
3-1. PAD をインストール
公式サイトから、ダウンロード、インストールしてください。詳細は割愛します。
3-2. 「新しいフロー」を作成
公式サイトなどを参考に、新しいフローの作成をしてください。詳細は割愛します。
3-3. アクションヒエラルキーの「新しい Chrome を起動する」を追加しパラメータを以下のように変更
3-4. アクションヒエラルキーの「Web ページのボタンを押します」を追加しパラメータを以下のように変更
3-5. 「▷ 実行」ボタンをクリック
3-6. 「chrome」が起動して、「google」にアクセスした後、「about.google」のページに更新
いかがでしたでしょうか?実際の開発では、エラー処理、例外処理、サブフローで分割、厳密な UI 要素の存在確認などで細かく設定しますが、イメージはつかんでいただけたと思います。
詳しく知りたい方は、「Power Automate Desktopについての記事」などをご参照ください。
4. Power Shell, batファイル と UIAutomation を使った自動化の例
Power Shellスクリプトは、Power Automate Desktopではできない部分を細かく実装することに向いています。本節では、RPAを作るのに非常に便利な「UIAutomation」ライブラリを使用して、UI要素の取得やクリックイベントの送信などを実装してみましょう。
4-1. UIAutomationライブラリの環境構築
UIAutomation.0.8.7B3.NET40 ライブラリをダウンロードします。(※リンク先は非公式です。公式がこのライブラリを廃止しているためです。)
https://www.code-lab.net/?page_id=21648
展開して C ドライブの直下などに置きます。
4-2. Inspect.exe環境構築
UIAutomationライブラリとともに使用する便利ツールとして、「Inspect.exe」があります。これは、WindowsアプリケーションのUI要素を可視化できるもので、後述するUIAutomationSpy.exeでUI要素が取得できなかったときの調査に役立ちます。
「 https://developer.microsoft.com/ja-jp/windows/downloads/sdk-archive/ 」に移動します。
「Windows 10 SDK バージョン 2104」の「SDK のインストール」を選択します。
デフォルト設定のまま、「Next」 で進んでいき、インストールをクリックします。
「Close」をクリックします。
4-3. 電卓を例に実装
ダウンロードしたUIAutomation.0.8.7B3.NET40ライブラリにある「UIAutomationSpy.exe」を起動します。
電卓を起動します。
UIAutomationSpyの「Start」ボタンをクリックして、電卓の「1」にマウスをフォーカスします。その後、素早くUIAutomationSpyのウィンドウにマウスをホバーして、「Stop」ボタンをクリックします。
UIAutomationSpyが自動でプログラムを生成したことがわかります。
batファイルを作成して、エンコードをShift-JISに指定して、以下のスクリプトを記述します。
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
cd 'C:\UIAutomation.0.8.7B3.NET40'
Import-Module .\UIAutomation.dll
Get-UiaWindow -Class 'CalcFrame' -Name '電卓' | `
Get-UiaPane -Class 'CalcFrame' | `
Get-UiaPane -Class '#32770' | `
Get-UiaButton -AutomationId '131' -Class 'Button' -Name '1'
このスクリプトの内容は以下の通りです。
batファイルを強制的に、Power Shellスクリプトとして読み込みます。先ほどダウンロードした「UIAutomation」ライブラリのフォルダまで移動します。ライブラリを読み込みます。先ほどの「UIAutomationSpy.exe」で作成されたプログラムをコピーして、このbatファイルに書き込みます。
batファイルを実行すると、エラーが発生する場合があります。以下のエラーは、classNameが「#32770」という名前のUI要素が見つからなかったことを指しています。
Get-UiaPane : failed to get control in 5000 milliseconds by: title: '', automationId: '', className: '#32770', value: '
'.
発生場所 行:8 文字:1
+ Get-UiaPane -Class '#32770' | `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationTimeout: (:) [Get-UiaPane], Exception
+ FullyQualifiedErrorId : ControlIsNull,UIAutomation.Commands.GetUiaPaneCommand
ここで使用するツールが、先ほどダウンロードした「inspect.exe」です。以下のような流れで、電卓のUI要素を調査します。
batプログラムのデバッグinspect.exeを起動ウィンドウ上部にあるアイコンを選択電卓のウィンドウをクリック、inspect.exeの左側に表示されているヒエラルキーからUI要素をフォーカスinspect.exeの右側に表示されている「Data View」から、それぞれのUI要素のプロパティを確認batプログラムを修正
それぞれ具体的に見ていきましょう。
4-3-1. batプログラムのデバッグ
以下のように一つずつプログラムを実行していきながら、どの部分でエラーが発生しているかを特定します。
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
cd 'C:\UIAutomation.0.8.7B3.NET40'
Import-Module .\UIAutomation.dll
# コメントアウト
# Get-UiaWindow -Class 'CalcFrame' -Name '電卓' | `
# Get-UiaPane -Class 'CalcFrame' | `
# Get-UiaPane -Class '#32770' | `
# Get-UiaButton -AutomationId '131' -Class 'Button' -Name '1'
Get-UiaWindow -Class 'CalcFrame' -Name '電卓'
Get-UiaWindow -Class 'CalcFrame' -Name '電卓' | `
Get-UiaPane -Class 'CalcFrame'
Get-UiaWindow -Class 'CalcFrame' -Name '電卓' | `
Get-UiaPane -Class 'CalcFrame' | `
Get-UiaPane -Class '#32770' # ここでエラーが発生
4-3-2. inspect.exeを起動
inspect.exeはのようなパスに格納されています。
"C:\Program Files (x86)\Windows Kits\10\bin\10.0.20348.0\x86\inspect.exe
4-3-3. ウィンドウ上部にあるアイコンを選択
以下の画像の内「①強調表示」と「②マウスクリック」と「③マウスホバー」と「④UI Automation」を選択します。
4-3-4. 電卓のウィンドウをクリック、inspect.exeの左側に表示されているヒエラルキーからUI要素をフォーカス
以下のように、マウスをクリックしたり、ヒエラルキーからUI要素を選択したりします。
4-3-5. inspect.exeの右側に表示されている「Data View」から、それぞれのUI要素のプロパティを確認
よく確認する部分は、主に「Name」と「ControlType」と「ClassName」です。
先ほどエラーが発生した箇所「Get-UiaPane -Class '#32770'」は、DataViewの「UiaPane」が「UIA_PaneControlTypeId」を、「 -Class '#32770' 」は「ClassName: "#32770"」を表しています。
以下の2つの画像は、電卓の計算結果表示用のUI要素のDataViewと、電卓の入力用ボタンのUI要素のDataViewを示しています。どちらも、「ClassName」が「 #32770 」で同じことが確認できます。
この調査結果から、「ClassName」が一意のUI要素を識別するものではなかったので、エラーが発生したと考えられます。
4-3-6. batプログラムを修正
結論は、以下のようなプログラムとなります。
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
cd 'C:\UIAutomation.0.8.7B3.NET40'
Import-Module .\UIAutomation.dll
Get-UiaWindow -Class 'CalcFrame' -Name '電卓' | `
Get-UiaPane -Class 'CalcFrame' | `
# Get-UiaPane -Class '#32770' | `
Get-UiaButton -AutomationId '131' -Class 'Button' -Name '1'
先ほどのプログラムの3つ目の「Get-UiaPane -Class '#32770' | `」行をコメントアウトすれば正常に動作します。
UI要素を正常に取得できたため、マウスクリックイベントを最後の行に次のように追加します。
Get-UiaButton -AutomationId '131' -Class 'Button' -Name '1' | Invoke-UiaButtonClick
4-4. PADのフローを実行することを例に実装してみましょう。
全体の流れは、以下の通りです。
以下のbatプログラムを作成作成したbatファイルをコマンドプロンプトなどで引数を指定して実行指定した文字列のPADのフローが実行されればOK
4-4-1. 以下のbatプログラムを作成
まずは、以下のようなbatプログラムをCドライブ直下において、エンコードが「Shift JIS」で作成します。
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
# coding: Shift JIS
$flowName = $Args[0]
Write-Host $flowName'を開始します。'
cd 'C:\UIAutomation.0.8.7B3.NET40'
Import-Module .\UIAutomation.dll
$PADConsoleHostExePath = "C:\Program Files (x86)\Power Automate Desktop\PAD.Console.Host.exe"
Start-Process $PADConsoleHostExePath
[UIAutomation.Preferences]::Highlight = $true
$start = Get-Date -format "yyyy/MM/dd HH:mm:ss"
$syncTime = 10
while ($true) {
Start-Sleep -Milliseconds 100
$total = [int](New-TimeSpan $start(Get-Date)).TotalSeconds
if ($total % $syncTime -eq 0) {
try {
Start-Sleep -Milliseconds 100
Get-UiaWindow -AutomationId 'ConsoleMainWindow' -Class 'WinAutomationWindow' -Name 'Power Automate' | `
Get-UiaCustom -Class 'ModalManager' | `
Get-UiaCustom -Class 'ProcessesToolBarView' | `
Get-UiaEdit -AutomationId 'SearchFlowTextField' -Class 'TextBox' -Name 'フローの検索' | Set-UiaEditText -Text $flowName
Get-UiaWindow -AutomationId 'ConsoleMainWindow' -Class 'WinAutomationWindow' -Name 'Power Automate' | `
Get-UiaCustom -Class 'ModalManager' | `
Get-UiaCustom -AutomationId '' -Class 'ProcessesView' -Name '' | `
Get-UiaDataGrid -AutomationId 'MyFlowsListGrid' -Class 'DataGrid' | `
Get-UiaDataItem -Name $flowName -Class 'DataGridRow' | `
Get-UiaCustom -Name $flowName -Class 'DataGridCell' | `
Get-UiaButton -Name '実行' -Class 'Button' | Invoke-UiaButtonClick
Get-UiaWindow -AutomationId 'ConsoleMainWindow' -Class 'WinAutomationWindow' -Name 'Power Automate' | `
Get-UiaCustom -Class 'ModalManager' | `
Get-UiaCustom -Class 'ProcessesToolBarView' | `
Get-UiaEdit -AutomationId 'SearchFlowTextField' -Class 'TextBox' -Name 'フローの検索' | Set-UiaEditText -Text ''
Write-Host "フローを正常に実行できました。"
break
}
catch {
Write-Host "フローが失敗しました。"
}
}
# 60秒後に終了
if ($total -eq 60) {
exit /b
}
}
このbatプログラムは、以下のことを行っています。
まず、batプログラムを強制的にPower Shellスクリプトとして読み込みます。コマンドラインから与えられた引数を$flowNameに格納します。この引数はPADのフロー名です。10秒間隔で、PADのフローの実行を試みます。成功すればプログラムを終了します。60秒立てば強制的に終了します。
4-4-2. 作成したbatファイルをコマンドプロンプトなどで引数を指定して実行
以下のように、コマンドラインから、実行したり、batファイルに記述して、実行したりします。
powershell "C:\PAD.bat 【ブログ用】GoogleChrome"
4-4-3. 指定した文字列のPADのフローが実行されればOK
UIAutomationのすごさを実感していただけたと思います。
技術書籍、インターネット上での情報が少ないので、調査するのが大変です。
5. Sikulix を使った自動化の例
Sikulixは、以下の画像やプログラムのように、画像処理やOCRなどをかんたんに実装することができます。
# coding:utf-8
def ClickPAD():
try:
doubleClick("1649756179692.png")
except FindFailed, e:
print("画像1が見つかりませんでした")
try:
doubleClick("SelectedPowerAutomateDesktop.png")
except FindFailed, e:
print("画像2が見つかりませんでした")
if __name__ == "__main__":
ClickPAD()
Power Automate DesktopをSikulixで起動してみましょう。
Sikulixの環境構築プログラムの説明実行
5-1. Sikulixの環境構築
Javaの環境構築をします。
公式サイトから、ダウンロード、インストールしてください。詳細は割愛します。
この記事は、openjdk 11.0.14で実行しています。
以下のサイトにアクセスします。
https://raiman.github.io/SikuliX1/downloads.html
「sikulixide-2.0.5.jar」をダウンロードします。
ダウンロードした「sikulixide-2.0.5.jar」ファイルをダブルクリックして以下のようなIDEが表示されれば環境構築は終了です。
5-2. プログラムの説明
doubleClickメソッドの引数は、ダブルクリックしたい画像のファイル名です。この画像は、SikulixIDEの「スクリーンショットを撮る」からキャプチャすることができます。もし画像を見つけることができなかった場合は、「FindFailed」例外を出力するようになっています。
# coding:utf-8
def ClickPAD():
try:
doubleClick("1649756179692.png")
except FindFailed, e:
print("画像1が見つかりませんでした")
try:
doubleClick("SelectedPowerAutomateDesktop.png")
except FindFailed, e:
print("画像2が見つかりませんでした")
if __name__ == "__main__":
ClickPAD()
5-3. 実行
SikulixIDE上にある「実行(&R)」や以下のようにコマンドラインから実行できます。
java -jar sikulixideのパス -r SikulixIDEで作成したプログラムのパス
java -jar sikulixide-2.0.5.jar -r Sample.sikuli
Sikulixは、技術書籍やインターネット上での情報が非常に多いので、調査するのが簡単です。
6. 自動化処理で大切なこと
個人的にRPAなどで自動化する際に重要だと思うことは、以下の4つです。
厳格な存在確認とエラーハンドリング自動化対象業務が標準的か属人的か、業務を言語化できるのか可観測性の実現真夜中など作業しない時間帯にスケジューリング
それぞれ詳しく見ていきましょう
6.1 厳格なエラーハンドリング
特に、マウスクリックや特殊キーの送信などCRUD処理における「CUD」系の操作を行うときは注意が必要です。「Alt + F4」のキーをウィンドウに送る場合、期待するウィンドウではなく、作業中のウィンドウや他のアプリのアップデート系のポップアップに送信されてしまう可能性が考えられるからです。よく、予期せぬポップアップウィンドウが出現したり、ブラウザのキャッシュが削除されていたり、UI 操作対象のアプリケーションがアップデートしたりしていて、正常に操作できないことがあります。
6.2 自動化対象業務が標準的か属人的か、業務を言語化できるのか
RPA 開発チームなどが存在する場合、依頼者は 5W1H や数字などを使ってパターンを言語化したり、目的などを明文化しないとそもそも RPA は作れません。(たとえ作れたとしても、開発者と依頼者で大きな認識違いが発生し、RPA が期待しない動作を起こし、データを壊してしまう可能性があります。)
6.3 可観測性の実現
エラーが発生しても、即原因がわかるよう、RPA 実行中は画面のスクリーンショットなどでモニタリング、分割した RPA プログラムがそれぞれ成功したか失敗したかをログ出力する必要があります。
例えば以下の bat プログラムのように RPA が実行しているときは、画面のキャプチャを Slack にポストするなどして、可観測性を実現します。
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
# coding: Shift JIS
$start = Get-Date -format "yyyy/MM/dd HH:mm:ss"
$screenshotPath = "C:\screenshot.png"
# $mention = '<@SlackのメンションID>'
$channel = 'SlackのチャネルID'
$token = 'Authorization: Bearer xoxb-1234-abcdefgh'
$syncTime = 5
while ($true) {
Start-Sleep -Milliseconds 1000
$total = [int](New-TimeSpan $start(Get-Date)).TotalSeconds
if ($total % $syncTime -eq 0) {
[Reflection.Assembly]::LoadWithPartialName("System.Drawing")
function screenshot([Drawing.Rectangle]$bounds, $path) {
$bmp = New-Object Drawing.Bitmap $bounds.width, $bounds.height
$graphics = [Drawing.Graphics]::FromImage($bmp)
$graphics.CopyFromScreen($bounds.Location, [Drawing.Point]::Empty, $bounds.size)
$bmp.Save($path)
$graphics.Dispose()
$bmp.Dispose()
}
$bounds = [Drawing.Rectangle]::FromLTRB(0, 0, 1920, 1080)
screenshot $bounds $screenshotPath
curl.exe -F file=@$screenshotPath -F channels=$channel -H $token https://slack.com/api/files.upload
}
if ($total -eq 600) {
exit
}
}
6.4 真夜中など作業しない時間帯にスケジューリング
人が作業中にRPAが実行すると、人の操作が影響してフローが正常に実行できなかったりします。
そのため、RPAは人が作業していない夜中にスケジューリングすべきでしょう。
具体的にはタスクスケジューラーを使います。
まず、タスクスケジューラーを起動して、右側のヒエラルキーから「タスクスケジューラーライブラリ」を選択して、左側の操作ウィンドウから「基本タスクの作成」をクリックします。
どのようなタスクをスケジューリングするかわかりやすいような名前を設定して、「次へ」ボタンを押します。
タスクトリガーで、イベントでタスクを実行するのか、毎日定時で実行するのかなどを選択します。
毎日スケジューリングを設定する場合は、実行する時間を設定します。
「プログラムの開始」を選択して、「次へ」ボタンを押します。
実行したいbatファイルを選択します。
プログラムのパスが設定されていることを確認して、「次へ」ボタンをクリックします。
「完了」を押します。
最後に追加したタスクを選択して、右側の操作ウィンドウにある「実行」ボタンをクリックして、正常に動作するかどうかを確認します。
7. 最後に
RPAツールは有志の方々が作ってくださったものです。感謝して大切に使いましょう。
また、業務を効率化することが目的なので、RPAツールを使うことが目的にならないように気を付けましょう。
プログラマ三大美徳である「怠惰」、「短気」、「傲慢」の重要性を意識して、「効率化できることは本当に全くないのか?」と小さなことでも業務に疑問を抱き、考えるだけではなく実際に「行動」し続けることが重要だと思います。