Microsoft UI Automation Framework 이해하기

안녕하세요, 여러분!

왠지 모르게 수동으로 하는 일들이 너무 귀찮아지는 그런 날이 있죠?

그런 당신을 위해 자동화의 신세계를 열어줄 놀라운 프레임워크를 소개하려고 합니다.

바로 Microsoft의 UI Automation Framework입니다.

복잡한 코드나 별도의 라이브러리 없이도 윈도우 응용 프로그램을 마음껏 조종할 수 있습니다.

어떻게 가능한지 함께 알아보시죠.



1. UI Automation Framework 이해하기

UI Automation Framework는 사용자 인터페이스를 자동화할 수 있도록 도와주는 라이브러리입니다.

이것은 단순히 마우스 클릭이나 키보드 입력을 프로그래밍 방식으로 제어할 수 있게 해주는 것 뿐만 아니라, 사용자 인터페이스의 구성 요소를 읽을 수도 있습니다.


핵심 개념들

Automation Element

이것은 사용자 인터페이스의 구성 요소를 나타냅니다. 버튼 하나도, 또는 전체 응용 프로그램 창도 될 수 있습니다.


Control Patterns

이는 UI 구성 요소를 분류하고 제어하는 데 사용됩니다. 예를 들어, 버튼과 체크박스는 InvokePattern을 지원하여 프로그래밍 방식으로 ‘클릭’할 수 있게 해줍니다.


Tree Walker

이것은 UI Automation 트리 구조를 순회할 수 있게 해주는 객체입니다.


Tree Scope

이것은 특정 automation element에서 시작하는 하위 트리의 범위를 설명합니다.



2. UI Automation 트리 구조

UI Automation 트리 구조를 간단하게 시각화하면 아래와 같이 나타낼 수 있습니다.

                        [RootElement]
                               |
                  -----------------------------
                 |               |             |
         [Application 1]   [Application 2] [Application 3]
                 |               |             |
            ---------       ------------    -------------
           |        |      |     |     |    |     |      |  
       [Button] [Label] [Button][Text][Label][Menu][Button]  
           |                                          |
        -------                                    -------
       |       |                                  |       |
    [Text]  [Image]                            [Item1]  [Item2]


핵심 개념들

컨트롤뷰 (Control View)

이 뷰에서는 Button, Menu, Item1, Item2와 같이 사용자와 상호작용할 수 있는 UI 요소만 볼 수 있습니다.


컨텐트뷰 (Content View)

이 뷰에서는 Text, Label, Item1, Item2와 같이 사용자에게 정보를 표시하는 요소만을 볼 수 있습니다.


로우뷰 (Raw View)

이 뷰에서는 트리의 모든 요소를 볼 수 있으므로, 위에 표현한 모든 노드가 포함됩니다. 이 뷰는 모든 UI 요소를 포함하고 있어, 가장 세밀한 단위의 작업이 가능합니다. 단, 이 뷰는 일반적인 상호작용에는 사용되지 않습니다.


코드를 통해 이러한 트리 구조를 탐색하게 되면, 원하는 UI 요소를 찾아 그것과 상호작용하는 것이 가능합니다.

이는 복잡한 자동화 작업에서 아주 중요한 기능입니다.



3. 예제 코드들

예제 코드 1: 노트패드 열고 텍스트 입력하기

먼저, 노트패드를 자동으로 열고 “Hello, World!”라고 입력해보겠습니다.

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows.Automation;

namespace RPAMagic
{
    class Program
    {
        static void Main(string[] args)
        {
            // 노트패드 실행
            Process.Start("notepad.exe");

            // 약간의 대기 시간
            Thread.Sleep(2000);

            // 노트패드 창을 찾습니다.
            AutomationElement notepad = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Untitled - Notepad"));

            // 텍스트 입력
            SendKeys("Hello, World!");

            // SendKeys 메소드
            static void SendKeys(string keys)
            {
                System.Windows.Forms.SendKeys.SendWait(keys);
            }
        }
    }
}


예제 코드 2: 계산기 앱으로 계산하기

// ... (기존 using 문장들)
using System.Windows.Automation;

// ...

// 계산기 실행
Process.Start("calc.exe");
Thread.Sleep(1000);  // 대기

// 계산기 창 찾기
AutomationElement calcWindow = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Calculator"));

// "1" 버튼 찾기
AutomationElement button1 = calcWindow.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "1"));

// 버튼 클릭
InvokePattern invokePattern = button1.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
invokePattern.Invoke();


예제 코드 3: 파일 탐색기에서 폴더 열기

// ... (기존 using 문장들)
using System.Windows.Automation;

// ...

// 파일 탐색기 실행
Process.Start("explorer.exe");
Thread.Sleep(2000);  // 대기

// 파일 탐색기 창 찾기
AutomationElement explorerWindow = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "File Explorer"));

// 주소창 찾기
AutomationElement addressBar = explorerWindow.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "addressBar"));

// 주소창에 텍스트 입력
ValuePattern valuePattern = addressBar.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
valuePattern.SetValue("C:\\Users");


예제 코드 4: TreeWalker로 모든 자식 요소 탐색하기

using System;
using System.Windows.Automation;

namespace TreeWalkingExample
{
    class Program
    {
        static void Main(string[] args)
        {
            AutomationElement rootElement = AutomationElement.RootElement;
            TreeWalker walker = TreeWalker.ControlViewWalker;
            WalkTheTree(walker, rootElement);
        }

        static void WalkTheTree(TreeWalker walker, AutomationElement element)
        {
            AutomationElement childElement = walker.GetFirstChild(element);
            while (childElement != null)
            {
                Console.WriteLine(childElement.Current.Name);
                WalkTheTree(walker, childElement);
                childElement = walker.GetNextSibling(childElement);
            }
        }
    }
}

이 코드는 Control View 기반으로 만든 TreeWalker 객체를 사용하여, UI Automation Tree의 모든 자식 요소를 재귀적으로 탐색하고 출력합니다.


예제 코드 5: 특정 프로그램의 UI 요소만 탐색하기

AutomationElement targetProgram = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "Your Program Name"));
TreeWalker walker = TreeWalker.ControlViewWalker;
WalkTheTree(walker, targetProgram);

이렇게하면 특정 프로그램의 UI 요소만을 대상으로 Tree를 탐색할 수 있습니다.



4. 마무리

이렇게하면 특정 프로그램의 UI 요소만을 대상으로 Tree를 탐색할 수 있습니다.

단순히 버튼을 클릭하거나 텍스트를 입력하는 것에서 그치지 않고, 트리 구조를 이해하고 이를 활용하면 더욱 다양하고 복잡한 작업을 자동화할 수 있습니다.

매우 흥미롭지 않나요? 당신이 지루한 일상에서 벗어나 새로운 가능성을 찾을 수 있기를 바랍니다.

다음에 또 뵙겠습니다! 🚀






정규표현식의 유용한 패턴
#집합찾기 #반복찾기 #역참조 #조건달기
A 액티비티에서 B 액티비티로 데이터 전달하기
#WorkflowFoundation #InArgument #OutArugment #Variables
Microsoft UI Automation Framework 이해하기
#AutomationElement #TreeWalker #ControlPatterns
AppDomain 탐구
#AppDomain #격리 #어셈블리별도실행 #플러그인시스템
Chrome Extension 활용하여여 웹 페이지 XPath 정보 가져오기
#ChromeExtension #크롬확장프로그램 #XPath
Workflow 디자이너와 액티비티의 관계
#WorkflowFoundation #Designer #Activity #ModelItem
ExpressionTextBox와 ModelItem의 바인딩 관계
#WorkflowFoundation #ExpressionTextBox #ModelItem #Binding
Windows 레지스트리 간단 정리
#Windows #Registry #레지스트리
WPF MVVM 패턴, 그리고 Binding
#WPF #MVVM #Binding #Modle #View #ViewModel
오라클 SQL 성능 최적화 - 바인드 변수와 Shared Memory 이해하기
#Oracle #바인드변수 #SharedMemory #LibraryCache #SqlPlan
ActivityDesigner와 CodeActivity 이해하기
#WorkflowFoundation #ActivityDesigner #CodeActivity
Selenium Implicit vs Explicit - 웹 요소 기다리기
#Selenium #IWebDriver #Implicit #Explicit
.NET에서 Selenium 활용하기 - 3가지 실전 예제
#Selenium #ChromeDriver #FindElements
.NET에서 CommandBinding 활용하기
#.NET #CommandBinding #디자인패턴
워크플로우 파운데이션(Workflow Foundation) 소개
#WorkflowFoundation #소개 #기본개념
AWS SAA 준비 - (4) 비용에 최적화된 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (3) 안전한 아키텍처
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (2) 성능이 뛰어난 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
AWS SAA 준비 - (1) 복원력을 갖춘 아키텍처 설계
(정리) Exam Readiness - AWS Solutions Architect Associate
15분 안에 ToC를 구현해보자!
Vanilla JS로 Table of Contents 구현하기
모듈
모던 자바스크립트 Deep Dive | 48장 | 모듈
에러 처리
모던 자바스크립트 Deep Dive | 47장 | 에러 처리
제너레이터와 async/await
모던 자바스크립트 Deep Dive | 46장 | 제너레이터와 async/await
프로미스
모던 자바스크립트 Deep Dive | 45장 | 프로미스
REST API
모던 자바스크립트 Deep Dive | 44장 | REST API
Ajax
모던 자바스크립트 Deep Dive | 43장 | Ajax
비동기 프로그래밍
모던 자바스크립트 Deep Dive | 42장 | 비동기 프로그래밍
타이머
모던 자바스크립트 Deep Dive | 41장 | 타이머
Set과 Map
모던 자바스크립트 Deep Dive | 37장 | Set과 Map
디스트럭처링
모던 자바스크립트 Deep Dive | 36장 | 디스트럭처링
브라우저의 렌더링 과정
모던 자바스크립트 Deep Dive | 38장 | 브라우저의 렌더링 과정
스프레드 문법
모던 자바스크립트 Deep Dive | 35장 | 스프레드 문법
이터러블
모던 자바스크립트 Deep Dive | 34장 | 이터러블
7번째 데이터 타입 Symbol
모던 자바스크립트 Deep Dive | 33장 | 7번째 데이터 타입 Symbol
String
모던 자바스크립트 Deep Dive | 32장 | String
RegExp
모던 자바스크립트 Deep Dive | 31장 | RegExp
Date
모던 자바스크립트 Deep Dive | 30장 | Date
Math
모던 자바스크립트 Deep Dive | 29장 | Math
DOM
모던 자바스크립트 Deep Dive | 39장 | DOM
Number
모던 자바스크립트 Deep Dive | 28장 | Number
배열
모던 자바스크립트 Deep Dive | 27장 | 배열
이벤트
모던 자바스크립트 Deep Dive | 40장 | 이벤트
ES6 함수의 추가 기능
모던 자바스크립트 Deep Dive | 26장 | ES6 함수의 추가 기능
클래스
모던 자바스크립트 Deep Dive | 25장 | 클래스
this
모던 자바스크립트 Deep Dive | 22장 | this
빌트인 객체
모던 자바스크립트 Deep Dive | 21장 | 빌트인 객체
strict mode
모던 자바스크립트 Deep Dive | 20장 | strict mode
클로저
모던 자바스크립트 Deep Dive | 24장 | 클로저
프로토타입
모던 자바스크립트 Deep Dive | 19장 | 프로토타입
함수와 일급 객체
모던 자바스크립트 Deep Dive | 18장 | 함수와 일급 객체
실행 컨텍스트
모던 자바스크립트 Deep Dive | 23장 | 실행 컨텍스트
생성자 함수에 의한 객체 생성
모던 자바스크립트 Deep Dive | 17장 | 생성자 함수에 의한 객체 생성
프로퍼티 어트리뷰트
모던 자바스크립트 Deep Dive | 16장 | 프로퍼티 어트리뷰트
let, const 키워드와 블록 레벨 스코프
모던 자바스크립트 Deep Dive | 15장 | let, const 키워드와 블록 레벨 스코프
전역 변수의 문제점
모던 자바스크립트 Deep Dive | 14장 | 전역 변수의 문제점
스코프
모던 자바스크립트 Deep Dive | 13장 | 스코프
함수
모던 자바스크립트 Deep Dive | 12장 | 함수
원시 값과 객체의 비교
모던 자바스크립트 Deep Dive | 11장 | 원시 값과 객체의 비교
객체 리터럴
모던 자바스크립트 Deep Dive | 10장 | 객체 리터럴
타입 변환과 단축 평가
모던 자바스크립트 Deep Dive | 9장 | 타입 변환과 단축 평가
제어문
모던 자바스크립트 Deep Dive | 8장 | 제어문
연산자
모던 자바스크립트 Deep Dive | 7장 | 연산자
데이터 타입
모던 자바스크립트 Deep Dive | 6장 | 데이터 타입
표현식과 문
모던 자바스크립트 Deep Dive | 5장 | 표현식과 문
변수
모던 자바스크립트 Deep Dive | 4장 | 변수
Iteration와 Generator
코드스피츠 77 ES6+ 3화 참조
WHATWG 탄생 배경
WHATWG, W3C, HTML의 관련에 대한 역사
프론트엔드(FE) 면접 질문 정리
FE관련 면접 질문 및 답변 정리한 내용입니다.
쿠버네티스(kubernetes, k8s) 용어 정리
쿠버네티스(kubernetes, k8s) 용어 정리
젠킨스(Jenkins) 정리
젠킨스(Jenkins) 정리
Docker 용어 정리
Docker 용어 정리
Git 용어 정리
Git 용어 정리
반응형 웹 디자인(Responsive Web Design)
CSS responsive 에 대하여
JS this에 대하여
this에 대해 알아보자
SQL*PLUS에 대하여
SQL*PLUS 정의 및 사용방법
Oracle에서 SQL Plan 확인하기
Oracle에서 SQL Plan을 확인해보자