桌面自動化 - Desktop Automation
這個模組使用電腦視覺技術分析螢幕找出參考圖案座標,操作滑鼠與鍵盤來達成桌面應用軟體的自動化。在部署內含桌面自動化技能時,電腦螢幕設定(如解析度、顏色深度、文字放大比例等)應與訓練模式時的電腦一致,建議最好是直接在部署電腦上設計流程,並避免於執行期間操作電腦造成滑鼠與鍵盤的干擾。

設定權限
由於需要分析螢幕,因此第一次打開這個模組時使用者需要同意「螢幕錄影」的權限;另外需要控制滑鼠與鍵盤因此使用者也要同意「輔助使用」相關的權限。


注意事項
- Windows 作業系統需要 Windows 10 64bit 以上版本,並事前安裝微軟 VC++ 函式庫。
- DA 技能運作時會占用滑鼠與鍵盤,如果自動化過程中移動滑鼠或使用鍵盤,自動化的結果有可能受到影響而產生錯誤。
- 使用者要確保輸入法(IME)的狀態與訓練時一致。有時系統對於不同的應用程式會出現輸入法自動切換,有可能導致錯誤的文字輸入。
訓練面板
點擊「TRAINER」可以啟動在桌面右上方的訓練面板,直接在本機進行桌面流程設計。當訓練面板出現後,建議將主界面與模組視窗最小化,這樣可以將空間騰出給訓練面板使用。

訓練面板分為三種模式:「桌面」,「No-Code 編輯器」,以及 「Low-Code 編輯器」。
桌面模式 - 是用來直接手動調整桌面或應用程式的操作狀態,我們可以自由的將桌面調整到流程開始時所需的狀態,然後點擊快門按鈕為 No-Code 模式取得螢幕快照;也可以利用 Ctrl/Cmd+0 的快捷鍵執行快照,或是 Ctrl/Cmd+5 快捷鍵執行延遲5秒的快照。

No-Code 編輯器 - 利用滑鼠操作帶出選單以選擇流程的新指令,然後將指令對應的程式碼寫入 Low-Code 編輯器。

Low-Code 編輯器 - 用來手動調整 No-Code 模式產生的程式碼,以達到最大化的設計彈性。

No-Code 編輯器
選單指令包含:OPEN FILE、INPUT TEXT、SEND KEYS、SLEEP、COPY XY、CLICK LEFT、CLICK RIGHT 等。其中 OPEN FILE 除了可以如同滑鼠雙擊指定檔案以啟動關聯的應用程式外,也可以選擇應用程式執行檔直接啟動應用程式。

例如,點選 OPEN FILE 新增一個指令打開會計軟體 Accounting.app。

當指令在 No-Code 編輯器產生後,會如下圖提醒使用者:

Low-Code 編輯器
切換到 Low-Code 編輯器可以檢查或調整程式碼,以這個例子是剛才新增指令 OPEN FILE 產生的。

在訓練面板上點擊「▶︎」執行鍵,EMILY.RPA 就會自動切換到桌面模式並開始執行 Low-Code 程式碼,按「■」 停止鍵或「Shift+ESC」可以中斷執行。

接著可以執行一次快照,取得最新螢幕畫面後切換回 No-Code 編輯器,繼續增加下一個指令,以滑鼠拖曳螢幕畫面上的按鈕區域,放開滑鼠後帶出指令選單,選取「CLICK CROP」增加指令,這個指令是讓 EMILY.RPA 在螢幕找到選取的參考圖案(CROP)再進行滑鼠點擊。需要找到螢幕上指定圖案的指令都會產生參考圖案在工作資料夾,檔案命名形式為 CROP-xxx.png。

當指令逐漸增加後,除了訓練面板的「▶︎」執行鍵可以循序執行全部步驟指令外,也可以在程式碼編輯區選取想要執行的程式碼區段,點擊編輯區上方的「RUN SELECTED CODE」執行選取行數的程式碼,下方的範例是執行第 6 行到第 16 行。

完成 Low-Code 程式碼後,一定要記得在 Low-Code 編輯器的訓練面板點擊執行鍵左邊的「COMMIT」鍵。第一次點擊「COMMIT」程式碼會從 TRIAL 區推送到 FINAL 區,第二次點擊才會把 FINAL 區的程式碼推送回模組視窗。

最後按下「SAVE」 才算完成桌面自動化並儲存。如果萬一忘了儲存,可以打開訓練模式的工作資料夾,剛才在 FINAL 區的程式碼會被儲存在 code-final-xxxx.js 的檔案中:

api.screen 物件
api.screen 提供螢幕資訊與螢幕分析相關非同步函式。
// 取得螢幕長寬
let size = await api.screen.size()
console.log(size)
// 在螢幕上指定區域內(可忽略)尋找與指定圖檔最相似位置
let found1 = await api.screen.find('crop-1234.png', {left:0,top:0,width:600,height:600})
console.log(found1)
// 在螢幕上需找與指定圖檔有95%以上相似的所有可能位置
let found2 = await api.screen.find('crop-1234.png', {confidence:0.95, all:true})
console.log(found2)
// 最長10秒等待螢幕上指定區域(可忽略)出現與指定圖檔最相似的位置
let found3 = await api.screen.waitFor('crop-5678', 10000, {left:0,top:0,width:600,height:600,confidence:0.95})
// 從螢幕(0,0)截取長寬都是100像素的圖片
await api.screen.capture('snapshot.png', 0, 0, 100, 100)
api.mouse 物件
api.mouse 提供滑鼠操作相關非同步函式。
// 設定滑鼠控制參數:點擊間延遲/移動速度/移動段數
const msDelay = 0 // 0 ms between clicks/scrolls
const mouseSpeed = 2000 // 2000 pixels per second of moving mouse
const mouseSteps = 30 // 30 how many steps in a mouse movement
api.mouse.config(msDelay, mouseSpeed, mouseSteps)
// 移動滑鼠游標至(x,y)
await api.mouse.move(x, y)
// 取得滑鼠游標位置 {x,y}
let pos = await api.mouse.getPosition()
console.log(pos)
// 點擊滑鼠左鍵後左鍵雙擊再點擊右鍵
await api.mouse.clickLeft()
await api.mouse.doubleClick()
await api.mouse.clickRight()
// 滑鼠點擊再釋放
await api.mouse.press()
await api.mouse.release()
// 將滑鼠游標從現在位置按住左鍵拖曳到(x,y)
const button = 0 // 0:左鍵, 1:滾輪鍵, 2:右鍵
await api.mouse.drag(x, y, button)
// 操作滑鼠滾輪往:上/下/左/右
await api.mouse.scrollUp(n)
await api.mouse.scrollDown(n)
await api.mouse.scrollLeft(n)
await api.mouse.scrollRight(n)ode
api.keyboard 物件
api.keyboard 提供鍵盤輸入相關非同步函式。
// 從鍵盤發送 hello
await api.keyboard.type('hello')
// 按住與釋放按鍵
await api.keyboard.press(api.key.A)
await api.keyboard.release(api.key.A)
// 發送鍵盤常用控制鍵 ENTER/ESC/BACK/TAB
await api.keyboard.enter()
await api.keyboard.escape()
await api.keyboard.backspace()
await api.keyboard.tab()
// 發送鍵盤組合鍵 ALT+F4
await api.keyboard.keys(api.key.LeftAlt, api.key.F4)
// 發送鍵盤:全選/複製/貼上
await api.ctrlA()
await api.ctrlC()
await api.ctrlV()
api 物件
提供其他簡化流程設計與操作 shell 的非同步函式。
// 找到與crop-2345最相似位置(信心程度95%)後點擊相對位移(x,y)並等待500ms後繼續下個指令, 找到後立即移動滑鼠游標無需軌跡 (instant: true)
await api.clickCrop('crop-2345', x, y, {confidence:0.95, wait:500, instant: true})
// 找到與crop-3456最相似位置(信心程度95%)後將滑鼠游標移到相對位移(x,y)並等待500ms後再繼續下個指令
await api.moveToCrop('crop-3456', x, y, {confidence:0.95, wait:500})
// 從found3(上方範例)相對位移(x,y)擷取長寬wxh螢幕截圖做OCR
// searchLine為搜尋文字結果的正規表達式,與下方moveCursor合併使用
// moveCursor為布林值,代表是否將滑鼠游標移至找到的searchLine在螢幕上的中心位置
// language為OCR的辨識語言: 'eng','chi_tra'
let result = await api.captureToOcr(found2, x, y, w, h, searchLine, moveCursor, language)
console.log(result.text)
// 貼上文字快捷鍵
await api.pasteText('hello')
// 讀寫剪貼簿同步函式
api.clipboard.writeText('hello')
console.log(api.clipboard.readText())
// 讀CSV檔API,分隔符號為逗點,讀取表頭須從檔頭略過0列
let rows = await api.readCSV('input.csv', ',', 0)
// 寫CSV檔API,表頭依序為name,age
await api.writeCSV('output.csv', [{name:'Alice',age:20},{name:'Bob',age:25}], ['name','age'])
// 等待5秒鐘
await api.sleep(5000)
// 執行其他技能
await api.run('bed383cd-ec5b-497e-ae4d-b9ad906e0abe')
// 開啟工作資料夾檔案
await api.shell.openPath('output.csv')
// 開啟任意檔案
await api.shell.openPath('/Users/emily/Desktop/input.xlsx')
// 開啟檔案總管並選取檔案
await api.shell.showItemInFolder('/Users/emily/Desktop/input.xlsx')
// 將檔案移至資源回收桶
await api.shell.trashItem('/Users/emily/Desktop/input.xlsx')
// 開啟網頁連結
await api.shell.openExternal('https://google.com')
// 執行 PowerShell 腳本
let result1 = await api.powerShell('Get-Process')
// 執行 PowerShell PS1 檔案腳本
let result2 = await api.powerShell('./myscript.ps1')
api.key 物件
下表為所有按鍵列表,例如空白鍵為 api.key.Space
Space Escape Tab Backspace Enter
LeftAlt RightAlt LeftControl RightControl LeftShift RightShift LeftSuper RightSuper
F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12
Num0 Num1 Num2 Num3 Num4 Num5 Num6 Num7 Num8 Num9
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Grave Minus Equal LeftBracket RightBracket Backslash Semicolon Quote Comma Period Slash
Left Up Right Down
Print Pause Insert Delete Home End PageUp PageDown
NumPad0 NumPad1 NumPad2 NumPad3 NumPad4 NumPad5 NumPad6 NumPad7 NumPad8 NumPad9
Add Subtract Multiply Divide Decimal
CapsLock ScrollLock NumLock