Desktop Automation (DA)

桌面自動化(Desktop Automation, 簡稱 DA) 是訓練EMILY分析與辨識螢幕並操作滑鼠與鍵盤來達成桌面應用軟體的流程自動化。請注意部署DA自動化技能的電腦螢幕設定(如解析度、顏色深度、文字放大比例等)應與訓練時的電腦完全一致,建議最好是直接在部署自動化的電腦上訓練技能,並避免於自動化技能執行期間操作電腦造成滑鼠與鍵盤的干擾

訓練介面

點擊 OPEN TRAINER UI 可以啟動訓練模式面板,直接在本機做 DA 流程的設計;或者利用同網段的另一台電腦瀏覽器,連入 Trainer URL 做遠端的流程設計:

當螢幕畫面右上角出現訓練模式面板後,建議將 EMILY 主界面與 WAP 視窗最小化,這樣可以將螢幕空間騰出給訓練模式使用。

訓練模式面板分為三種模式:Live,No-Code,以及 Low-Code。Live 模式是用來手動調整桌面或應用程式的操作狀態;No-Code 模式是利用滑鼠操作帶出選單以選擇流程步驟的指令,最終會將指令寫入 Low-Code 模式的程式碼編輯區;最後 Low-Code 模式是用來手動調整 No-Code 模式產生的程式碼,以達到最大化的設計彈性。

在 Live 模式,我們可以自由的將桌面調整到流程開始時所需的狀態,然後點擊快門按鈕為 No-Code 模式取得螢幕快照;也可以利用 Ctrl/Cmd+0 的快捷鍵執行快照,或是 Ctrl/Cmd+5 快捷鍵執行延遲5秒的快照。

進入 No-Code 模式後可以單點滑鼠帶出選單以選擇要產生的步驟指令:OPEN FILE, INPUT TEXT, SEND KEYS, SLEEP, COPY XY, CLICK LEFT, CLICK RIGHT 等。其中 OPEN FILE 除了可以如同滑鼠雙擊指定檔案以啟動關聯的應用程式外,也可以選擇應用程式執行檔直接啟動應用程式。

當步驟指令在 No-Code 模式下產生後,會如下圖提醒使用者已產生指令:

這時可以切換到 Low-Code 模式檢查或調整程式碼:

在任一模式下點擊訓練模式面板上的 ▶︎ 執行鍵,EMILY 就會自動切換到 Live 模式並開始依指令順序執行,按 ■ 停止鍵或 Shift+ESC 可以中斷執行:

接著可以執行一次快照,取得最新螢幕畫面後切換回 No-Code 模式,繼續增加下一個步驟指令,例如以滑鼠拖曳螢幕畫面上的按鈕區域,放開滑鼠後帶出選單並選取加入的下一個步驟指令:

當步驟指令逐漸增加後,除了訓練模式面板的 ▶︎ 執行鍵可以循序執行全部步驟指令外,也可以在程式碼編輯區選取想要執行的程式碼區段,點擊編輯區上方的 RUN SELECTED CODE 執行選取部份的步驟指令:

在完成所有步驟指令後,一定要記得 Commit 程式碼。由於步驟指令會被加入 TRIAL 程式碼區域,點擊訓練模式面板內的 Commit 鍵會推送到 FINAL 區,必須再 Commit 一次才會推送回 DA WAP 視窗:

此時按下 SAVE 按鈕才算完成 DA WAP 的流程段。如果萬一忘了 SAVE,可以打開訓練模式的工作資料夾,剛才在 FINAL 程式編輯區 Commit 的程式碼會被儲存在 code-final-xxxx.js 的檔案中:

請注意以下的限制

  1. Windows 作業系統需要 Windows 10 64bit 以上版本,並事前安裝微軟 VC++ 函式庫

  2. DA 技能運作時會占用滑鼠與鍵盤,如果自動化過程中移動滑鼠或使用鍵盤,自動化的結果有可能受到影響而產生錯誤。

  3. 使用者要確保輸入法(IME)的狀態與訓練時一致。有時系統對於不同的應用程式會出現輸入法自動切換,有可能導致錯誤的文字輸入。

Low-Code API

// 取得螢幕長寬
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)

// 找到與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)

// 設定滑鼠控制參數:點擊間延遲/移動速度/移動段數
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()

// 將滑鼠游標從現在位置按住左鍵拖曳到(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)

// 從鍵盤發送 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.type(api.key.LeftAlt, api.key.F4)

// 發送鍵盤:全選/複製/貼上
await api.ctrlA()
await api.ctrlC()
await api.ctrlV()

// 貼上文字快捷鍵
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.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 提供按鍵碼如下:

Space 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 Backspace LeftBracket RightBracket Backslash Semicolon Quote Return 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

Last updated