Microsoft MVP성태의 닷넷 이야기
Windows: 192. Power Automate Desktop (Preview) 소개 - Bitvise SSH Client 제어 [링크 복사], [링크+제목 복사]
조회: 1035
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

Power Automate Desktop (Preview) 소개 - Bitvise SSH Client 제어

요즘 RPA(Robotic Process Automation)라는 영역이 뜨겁군요. ^^

RPA를 아주 단순하게 생각하면 기존의 AutoHotkey 프로그램이 하던 것이라고 떠올리면 됩니다. 단지, 이것을 좀 더 업무 친화적으로 포장하고 심지어 AI와도 연동을 한다면 고부가 가치의 RPA 솔루션이 될 수 있습니다.

당연히 운영체제와 오피스 제품군을 소유하고 있는 마이크로소프트가 이 분야를 보고만 있을 수는 없겠지요,

Microsoft Power Automate 설명서
; https://docs.microsoft.com/ko-kr/power-automate/

그리고, 바로 며칠 전의 Ignite 2021 행사에서 (Power Automate 기능의 일부를 담당하는) Power Automate Desktop을 (Windows 10 운영체제를 대상으로 Preview 버전을) 무료 배포하기 시작했습니다.

Easily automate anything from your desktop
; https://flow.microsoft.com/en-us/desktop/

Download the Power Automate Desktop installer
; https://go.microsoft.com/fwlink/?linkid=2102613

실제로 이걸 가지고 한 번 실습을 해볼까요? ^^

마침, 제 경우에 언제나 운영체제를 시작 후 Bitvise SSH Client를 실행시켜 로그인하는 작업이 좀 귀찮았습니다. 즉, 다음과 같은 작업을 꼭 해야 했는데,

  1. Action - Bitvise SSH Client 실행
  2. Action - Login 버튼 클릭
  3. Action - Bitvise SSH Client 윈도우 닫기

이것을 Power Automate Desktop으로 자동화해보겠습니다. ^^




자, 그럼 "Power Automate Desktop" 프로그램을 실행하고, "New flow" 링크를 눌러 새로운 자동화 기능 추가를 시작합니다.

pad_bitvise_login_1.png

"Create" 버튼을 누르면 이제 각각의 "Actions"를 구성할 수 있는 윈도우가 새로 뜨는데요,

pad_bitvise_login_2.png

첫 번째로 필요한 Action이 "Bitvise SSH Client"를 실행하는 것이므로, 위의 화면에서 보는 바와 같이 좌측의 "Actions" 패널에서 "System" 범주의 "Run application"을 선택, Bitvise 프로그램의 경로를 "Application path"에 넣고 "Save" 버튼을 누릅니다.

이후, 실행되는 화면에서 "Login" 버튼을 클릭하면 되지만 여기서 주의해야 할 것이 있습니다. 즉, exe 프로세스가 실행해 윈도우 화면까지 나오려면 시간이 걸리는데 이를 위한 적절한 대기가 필요하게 됩니다. 관련해서 방식은 다양하게 처리할 수 있는데요, 가령, 위의 "Run application" 설정 창에서도 "After application launch:" 설정에서 "Continue immediately" 옵션이 아닌, "Wait for application to load" 옵션과 함께 "Timeout"을 5초 정도로 지정할 수 있습니다. 그런 경우, EXE 실행 후 무조건 5초 대기 후 다음 Action을 실행하는 단계로 진행합니다.

물론, 저렇게 무조건 대기를 하기보다는 Actions의 "Wait" 범주에서 "Wait for window"를 추가해 다음의 매개변수로 설정하는 것이 좀 더 매끄러울 것입니다.

Find window: By window UI element
Window: %appmask['Window \'Bitvise SSH Client 8.43\'']%
Wait for window to: Open

여기서, 위의 "Window" 조건 값이 난해할 수 있는데, 해당 설정을 할 수 있는 "Added a new UI element" 버튼이 제공되므로 이를 이용해 (텍스트 입력 없이) 마우스 클릭만으로 윈도우 지정을 할 수 있습니다. (해당 UI는 다음 단계에서 소개합니다.)

자, 이렇게 해서 프로그램을 실행해 윈도우가 뜨는 것까지 진행했다면 이제 "Login" 버튼을 눌러 줄 수 있습니다. 이를 위해 "Actions" 패널에서 "UI automation" 범주의 "Click UI element in window"를 선택해,

pad_bitvise_login_3.png

보이는 우측의 대화창에서 "UI element:" 콤보 박스를 아래로 펼치면 "Add a new UI element"를 버튼이 보입니다. 해당 버튼을 누르면 다음과 같은 화면으로 진입하고,

pad_bitvise_login_4.png

"Login" 위로 마우스를 가져가면 위의 화면에서 보는 것처럼 대상 버튼이 빨간색 테두리로 인식이 되면서 이때 "Ctrl + 마우스 우 클릭"을 하면 그 버튼의 조건이 다음과 같은 식으로 등록이 됩니다.

UI element: %appmask['Window \'Bitvise SSH Client 8.43\'']['Button \'Log in\'']%
Click type: Left click

대충 등록 방식이 감이 오시죠? ^^

참고로, 위와 같이 Action을 직접 정의하는 것뿐만 아니라 "Actions" 문자열 우측에 있는 "Web Recorder", "Desktop Recorder"를 이용해,

pad_bitvise_login_5.png

사용자의 동작을 기록해 재생하는 것도 가능합니다.

Record flows in Power Automate Desktop
; https://docs.microsoft.com/en-us/power-automate/desktop-flows/recording-flow

Generate Power Automate Desktop flows by recording
; https://docs.microsoft.com/en-us/learn/modules/pad-power-automate-desktop-recording-features/




자, 그런데 마지막 동작이 애매합니다. Bitvise 응용 프로그램은 Login 후 더 이상 화면에 있을 필요가 없고 작업 표시줄에도 아이콘이 나와 있을 필요가 없습니다. 이를 위해서는 윈도우의 상단 우측에 있는 "X" 버튼을 눌러야 하는데요. 이를 위해 이미 앞 단계에서 진행한 "UI automation" / "Click UI element in window"로 "X" 버튼을 누르게 처리할 수 있겠지만, 아쉽게도 Bitvise 내부 동작은 일반 윈도우와는 달라서인지 정상적으로 통하지 않습니다. 심지어 다음과 같이 오류가 발생하기까지 합니다.

Flow 'bitvise login' failed
Error in 'main', action #3 'Click UI element in window'

Subflow: Main, Action: Click UI element in window

Click failed (failed to get UI element)

: Robin.Core.ActionException: Click failed (failed to get UI element)
   at Robin.Modules.UIAutomation.Actions.ClickElementInWindow.Execute(ActionContext context)
   at Robin.Runtime.Engine.ActionRunner.RunAction(String action, Dictionary`2 inputArguments, Dictionary`2 outputArguments, IActionStatement statement)

이에 대한 또 다른 처리 방식으로 "UI automation" / "Windows" / "Close window" 동작이 있지만, 일반적인 윈도우 응용 프로그램이라면 역시 이것도 동작했겠지만 Bitvise는 이 동작이 통하지 않습니다.

대신 Bitvise는 "UI automation" / "Windows" / "Set window visibility" 동작을 정의하는 것으로 해당 목적을 이룰 수 있습니다.

즉, 일반적인 동작으로 대부분의 응용 프로그램이 자동화될 수는 있지만 간혹 특정 프로그램들은 '일반적인 동작'을 따르지 않을 수도 있기 때문에 적절한 우회 방법을 찾아야 한다는 것을 고려해야 합니다.




여기까지 action을 정의했으면 이제 "File" / "Save (Ctrl + S)" 메뉴를 선택해 저장, 다음과 같이 해당 자동화 작업을 목록에서 확인할 수 있습니다.

pad_bitvise_login_6.png

이제 삼각형 모양의 Run 버튼을 누르면, 정의한 action에 따라 작업들이 차례대로 실행이 됩니다.

어떠세요? RPA라는 게 별거 아니죠? ^^ 사실 개발자 입장에서는 이미 CI/CD나 각종 WebHook을 이용한 처리들이 RPA 영역에 속한다고 볼 수 있습니다. 단지, 근래의 RPA 솔루션들이 의미가 있는 것은 그러한 자동화 작업들을 "코드 한 줄 없이" 가능하게 만들어 준다는 점입니다. 따라서 비-개발자들, 일례로 지식 근로자(knowledge worker)라고 불리거나 심지어 시민 개발자(citizen developer)들이 회사 등에서의 업무를 쉽게 자동화할 수 있다는 데에 의미가 있습니다. 혹은, 그냥 일반적인 윈도우 사용자라면 괜찮은 Toy 프로그램 하나 나온 정도가 되겠군요. ^^

그러고 보니, 이 분야의 전통적인 전문가라면 게임 프로그램들에 대한 각종 매크로 제작자들을 빼놓을 수 없을 것입니다. ^^




아직 Preview 버전이라 앞으로 어느 정도까지 기능이 발전할지는 모르겠지만 아쉬운 것들이 좀 있습니다. 가령, 저렇게 저장한 flow를 사용자가 직접 "Run" 버튼을 누르지 않고 프로그램에 의해 실행하는 방법이 아직 제공되지 않는 듯합니다.

참고로, Power Automate Desktop 프로그램이 flow를 실행할 때 자식 프로세스로 PAD.Runtime.Robot.exe를 다음과 같은 인자로 실행하는 것을 확인할 수 있습니다.

"C:\Program Files (x86)\Power Automate Desktop\PAD.Runtime.Robot.exe" --path "%LOCALAPPDATA%\Microsoft\Power Automate Desktop\Console\Workspace\b2564e2f-e5fe-47ce-9d94-5b94ead3762b\package" --instanceId 2e1bfe8462cd4b7ca000c78007cbadef --varPreviewChars 128 --varPreviewLines 5


아쉽게도 저 인자들 중에는 우리가 저장한 flow와 연관 지을 수 어떠한 값도 없지만, 실제로 그냥 단일 cmd 창에서 저대로 다시 실행해도 flow가 실행되지 않고 이런 오류만 발생합니다.

Unhandled Exception: System.Resources.MissingManifestResourceException: Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure "Robin.Runtime.Robot.Properties.Resources.resources" was correctly embedded or linked into assembly "PAD.Runtime.Robot" at compile time, or that all the satellite assemblies required are loadable and fully signed.
   at System.Resources.ManifestBasedResourceGroveler.HandleResourceStreamMissing(String fileName)
   at System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo culture, Dictionary`2 localResourceSets, Boolean tryParents, Boolean createIfNotExists, StackCrawlMark& stackMark)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
   at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
   at Robin.Runtime.Robot.HostProgram.OnExecute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.Invoke(MethodInfo method, Object instance, Object[] arguments)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<OnExecute>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at McMaster.Extensions.CommandLineUtils.Conventions.ExecuteMethodConvention.<>c__DisplayClass0_0.<<Apply>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.<>c__DisplayClass142_0.<OnExecute>b__0()
   at McMaster.Extensions.CommandLineUtils.CommandLineApplication.Execute[TApp](CommandLineContext context)
   at Robin.Runtime.Robot.HostProgram.Main(String[] args)

어쨌든 해당 flow가 저장된 경로는 위의 검토를 통해서 알게 되었는데요, 실제로 우리가 추가한 4가지 action은 "%LOCALAPPDATA%\Microsoft\Power Automate Desktop\Console\Workspace\b2564e2f-e5fe-47ce-9d94-5b94ead3762b\script.robin" 파일에서 찾을 수 있습니다.

IMPORT '%LOCALAPPDATA%\\Microsoft\\Power Automate Desktop\\Console\\Workspace\\b2564e2f-e5fe-47ce-9d94-5b94ead3762b\\controlRepo.appmask' AS appmask
IMPORT '%LOCALAPPDATA%\\Microsoft\\Power Automate Desktop\\Console\\Workspace\\b2564e2f-e5fe-47ce-9d94-5b94ead3762b\\imageRepo.imgrepo' AS imgrepo


System.RunApplication ApplicationPath: $'''C:\\Program Files (x86)\\Bitvise SSH Client\\BvSsh.exe''' WindowStyle: System.ProcessWindowStyle.Normal ProcessId=> AppProcessId
WAIT (UIAutomation.Windows.ToOpen Window: appmask['Window \'Bitvise SSH Client 8.43\''] FocusWindow: False) 
UIAutomation.Click Element: appmask['Window \'Bitvise SSH Client 8.43\'']['Button \'Log in\''] ClickType: UIAutomation.ClickType.LeftClick MousePositionRelativeToElement: UIAutomation.RectangleEdgePoint.MiddleCenter OffsetX: 0 OffsetY: 0
UIAutomation.Windows.SetVisibility Window: appmask['Window \'bit ...  Bitvise SSH Client\''] Visibility: UIAutomation.Visibility.Hidden

따라서 나중에 Bitvise 프로그램의 버전이 바뀌어 8.44가 되었을 때, Power Automate Desktop을 이용해 action을 UI 상에서 편집할 수도 있겠지만 script.robin 파일의 appmask 값을 직접 수정해 저장하는 것도 가능합니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]



donaricano-btn



[최초 등록일: ]
[최종 수정일: 3/28/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 쓴 사람
 



2021-03-11 12시13분
정성태

1  2  3  4  5  6  7  8  9  10  11  [12]  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
12575정성태3/24/2021734개발 환경 구성: 557. Docker Desktop for Windows에서 DockerDesktopVM 기반의 Kubernetes 구성
12574정성태3/23/20211140.NET Framework: 1030. C# Socket의 Close/Shutdown 동작 (동기 모드)
12573정성태3/22/2021905개발 환경 구성: 556. WSL 인스턴스 초기 설정 명령어
12572정성태3/22/2021807.NET Framework: 1029. C# - GC 호출로 인한 메모리 압축(Compaction)을 확인하는 방법파일 다운로드1
12571정성태3/21/2021811오류 유형: 706. WSL 2 기반으로 "Enable Kubernetes" 활성화 시 초기화 실패 [1]
12570정성태3/19/2021841개발 환경 구성: 555. openssl - CA로부터 인증받은 새로운 인증서를 생성하는 방법
12569정성태3/18/20211016개발 환경 구성: 554. WSL 인스턴스 export/import 방법 및 단축 아이콘 설정 방법
12568정성태3/18/2021673오류 유형: 705. C# 빌드 - Couldn't process file ... due to its being in the Internet or Restricted zone or having the mark of the web on the file.
12567정성태3/17/2021720개발 환경 구성: 553. Docker Desktop for Windows를 위한 k8s 대시보드 활성화 [1]
12566정성태3/17/2021797개발 환경 구성: 552. Kubernetes - kube-apiserver와 REST API 통신하는 방법 (Docker Desktop for Windows 환경)
12565정성태3/17/2021584오류 유형: 704. curl.exe 실행 시 dll not found 오류
12564정성태3/16/2021684VS.NET IDE: 160. 새 프로젝트 창에 C++/CLI 프로젝트 템플릿이 없는 경우
12563정성태3/16/2021738개발 환경 구성: 551. C# - JIRA REST API 사용 정리 (3) jira-oauth-cli 도구를 이용한 키 관리
12562정성태3/15/2021829개발 환경 구성: 550. C# - JIRA REST API 사용 정리 (2) JIRA OAuth 토큰으로 API 사용하는 방법파일 다운로드1
12561정성태3/12/2021659VS.NET IDE: 159. Visual Studio에서 개행(\n, \r) 등의 제어 문자를 치환하는 방법 - 정규 표현식 사용
12560정성태3/11/20211050개발 환경 구성: 549. ssh-keygen으로 생성한 개인키/공개키 파일을 각각 PKCS8/PEM 형식으로 변환하는 방법
12559정성태3/11/2021740.NET Framework: 1028. 닷넷 5 환경의 Web API에 OpenAPI 적용을 위한 NSwag 또는 Swashbuckle 패키지 사용파일 다운로드1
12558정성태3/10/20211035Windows: 192. Power Automate Desktop (Preview) 소개 - Bitvise SSH Client 제어 [1]
12557정성태3/10/2021585Windows: 191. 탐색기의 보안 탭에 있는 "Object name" 경로에 LEFT-TO-RIGHT EMBEDDING 제어 문자가 포함되는 문제
12556정성태3/9/2021540오류 유형: 703. PowerShell ISE의 Debug / Toggle Breakpoint 메뉴가 비활성 상태인 경우
12555정성태3/8/2021771Windows: 190. C# - 레지스트리에 등록된 DigitalProductId로부터 라이선스 키(Product Key)를 알아내는 방법파일 다운로드2
12554정성태3/8/2021974.NET Framework: 1027. 닷넷 응용 프로그램을 위한 PDB 옵션 - full, pdbonly, portable, embedded
12553정성태3/5/2021842개발 환경 구성: 548. 기존 .NET Framework 프로젝트를 .NET Core 용으로 변환해 주는 upgrade-assistant, try-convert 도구 소개
12552정성태3/5/2021631개발 환경 구성: 547. github workflow/actions에서 Visual Studio Marketplace 패키지 등록하는 방법
12551정성태3/5/2021658오류 유형: 702. 비주얼 스튜디오 - The 'CascadePackage' package did not load correctly. (2)
12550정성태3/5/2021602오류 유형: 701. Live Share 1.0.3713.0 버전을 1.0.3884.0으로 업데이트 이후 ContactServiceModelPackage 오류 발생하는 문제
1  2  3  4  5  6  7  8  9  10  11  [12]  13  14  15  ...