NGMsoftware

NGMsoftware
로그인 회원가입
  • 매뉴얼
  • 학습
  • 매뉴얼

    학습


    C# C# .NET 매크로 프로그램 만들기. (웹 업무 자동화 탐색 기능 구현)

    페이지 정보

    본문

    안녕하세요. 엔지엠소프트웨어입니다. 오늘은 웹 업무 자동화 RPA 프로그램을 이용해서 탐색 기능을 구현 해보겠습니다. 여기에서 탐색은 웹페이지에서 버튼, 링크, 텍스트 입력등등... 어떤 동작을 수행하는 엘리먼트(Element: 요소)를 찾는게 아닌 페이지와 관련된 내용입니다. 웹자동화를 만들려면 우선, 작업을 진행할 웹페이지에 접근해야 하잖아요? 그래서, 페이지에 접근하는 다양한 방법을 먼저 만들어야 합니다. 그리고, 엘리먼트에 접근해서 액션을 수행할 수 있도록 해줘야 합니다.

     

    우선, 외부 API의 웹/인터넷에서 웹 제어라는 액션을 만들어야 합니다.

    9VrRWjo.png

     

     

    기본적으로 이 액션도 연결된 웹세션이 있어야 하기 때문에 연결된 브라우저의 이름을 선택해야 합니다. 그래서, WebBaseModel을 상속 받아서 기본적인 속성들은 자동으로 처리될 수 있도록 해주었습니다. 추가로, 필요한 인터페이스가 있으면 따로 구현해야 하는데요. 현재 상태에서는 딱히 필요한게 없어 보입니다.

    public class NavigationModel : WebBaseModel

     

    기본적인 정보들을 표시하기 위해 핸들 정보도 추가 해줍니다.

    [LocalizedCategory("Data")]
    [LocalizedDisplayName("CurrentWindowHandle")]
    [LocalizedDescription("CurrentWindowHandle")]
    [Browsable(true)]
    [DefaultValue(null)]
    [Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
    public string? CurrentWindowHandle { get; set; }
    
    [LocalizedCategory("Data")]
    [LocalizedDisplayName("WindowHandles")]
    [LocalizedDescription("WindowHandles")]
    [Browsable(true)]
    [DefaultValue(null)]
    public string[]? WindowHandles { get; set; }

     

    사용자가 선택하거나 입력해야 할 명령은 2개밖에 없습니다. 생각보다 내용이 간단한데요. 엔지엠 매크로 6에서는 하나의 액션에 너무 많은 기능을 넣어두어서 퍼포먼스도 떨어지고 코드량도 많아서 분석에 어려움이 많았습니다. 그래서, 이번에는 좀 더 타이트하게 행동을 분류해서 액션들을 나누는 방향으로 진행 했습니다. 하지만, 아직도 일부 액션들은 많은 옵션과 설정 값으로 인해 복잡도가 높은데요. 연관성이 이어지는 경우에는 어쩔 수 없을듯 합니다.

    [LocalizedCategory("Action")]
    [LocalizedDisplayName("WebAction")]
    [LocalizedDescription("WebAction")]
    [Browsable(true)]
    [DefaultValue(typeof(Ai.Definition.NavigationOption), "GoToUrl")]
    public Ai.Definition.NavigationOption WebAction { get; set; } = Definition.NavigationOption.GoToUrl;
    
    [LocalizedCategory("Action")]
    [LocalizedDisplayName("ActionParameter")]
    [LocalizedDescription("ActionParameter")]
    [Browsable(true)]
    [DefaultValue(null)]
    public string? ActionParameter { get; set; }

     

    웹 액션의 종류에 따라서 처리를 분기 해줍니다.

    switch (WebAction)
    {
        case Definition.NavigationOption.GoToUrl:
            driver.Navigate().GoToUrl(ActionParameter);
            break;
        case Definition.NavigationOption.Forward:
            driver.Navigate().Forward();
            break;
        case Definition.NavigationOption.Back:
            driver.Navigate().Back();
            break;
        case Definition.NavigationOption.Refresh:
            driver.Navigate().Refresh();
            break;
        case Definition.NavigationOption.NewWindow:
            driver.SwitchTo().NewWindow(OpenQA.Selenium.WindowType.Window);
            break;
        case Definition.NavigationOption.NewTab:
            driver.SwitchTo().NewWindow(OpenQA.Selenium.WindowType.Tab);
            break;
        case Definition.NavigationOption.Close:
            driver.Close();
            break;
        case Definition.NavigationOption.CloseAll:
            foreach (var windowHandle in driver.WindowHandles)
            {
                driver.SwitchTo().Window(windowHandle);
                driver.Close();
            }
            break;
        case Definition.NavigationOption.SelectFirstWindow:
            driver.SwitchTo().Window(driver.WindowHandles.First());
            break;
        case Definition.NavigationOption.SelectLastWindow:
            driver.SwitchTo().Window(driver.WindowHandles.Last());
            break;
        case Definition.NavigationOption.SelectWindowName:
            string currentWindow = driver.CurrentWindowHandle;
    
            foreach (var windowHandle in driver.WindowHandles)
            {
                if (driver.SwitchTo().Window(windowHandle).Title == ActionParameter)
                    currentWindow = windowHandle;
                    break;
            }
    
            driver.SwitchTo().Window(currentWindow);
            break;
        case Definition.NavigationOption.SelectWindowNameByStartsWith:
            currentWindow = driver.CurrentWindowHandle;
    
            foreach (var windowHandle in driver.WindowHandles)
            {
                if (driver.SwitchTo().Window(windowHandle).Title.StartsWith(ActionParameter))
                    currentWindow = windowHandle;
                break;
            }
    
            driver.SwitchTo().Window(currentWindow);
            break;
        case Definition.NavigationOption.SelectWindowNameByEndsWith:
            currentWindow = driver.CurrentWindowHandle;
    
            foreach (var windowHandle in driver.WindowHandles)
            {
                if (driver.SwitchTo().Window(windowHandle).Title.EndsWith(ActionParameter))
                    currentWindow = windowHandle;
                break;
            }
    
            driver.SwitchTo().Window(currentWindow);
            break;
        case Definition.NavigationOption.SelectWindowNameByContains:
            currentWindow = driver.CurrentWindowHandle;
    
            foreach (var windowHandle in driver.WindowHandles)
            {
                if (driver.SwitchTo().Window(windowHandle).Title.Contains(ActionParameter))
                    currentWindow = windowHandle;
                break;
            }
    
            driver.SwitchTo().Window(currentWindow);
            break;
        case Definition.NavigationOption.SelectWindowIndex:
            driver.SwitchTo().Window(driver.WindowHandles[int.Parse(ActionParameter)]);
            break;
        case Definition.NavigationOption.IFrameById:
            var iframes = driver.FindElements(OpenQA.Selenium.By.TagName("iframe"));
            
            foreach (var iframe in iframes)
            {
                if (iframe.GetAttribute("id") == ActionParameter)
                {
                    driver.SwitchTo().Frame(iframe);
                    break;
                }
            }
            break;
        case Definition.NavigationOption.IFrameByName:
            driver.SwitchTo().Frame(ActionParameter);
            break;
        case Definition.NavigationOption.IFrameByIndex:
            driver.SwitchTo().Frame(int.Parse(ActionParameter));
            break;
        case Definition.NavigationOption.ParentIFrame:
            driver.SwitchTo().ParentFrame();
            break;
        case Definition.NavigationOption.IFrameToMain:
            driver.SwitchTo().DefaultContent();
            break;
    }

     

    위의 코드가 그렇게 복잡하거나 어렵지는 않을겁니다. 코드를 유심히 보면, 동일한 코드가 반복되고 있는데요. 그 안에서 각각의 메소드만 다르게 적용시키고 있습니다. 그래서, 옵션에 따라서 접근할 위치와 접근하기 위한 값을 설정하는 것으로 대부분의 처리가 가능해집니다. 물론, 일부 예외도 있지만 이런 것들은 별도로 다루는걸로 해야 할듯 합니다. 아무래도 일관성을 해치는 기능을 여기에 포함시켜서 옵션과 설정 값을 추가하기 보다는 심플하게 가져가는게 좋겠다는 판단이거든요^^

     

    아래 동영상은 다양한 방법으로 웹페이지를 탐색하는 방법을 설명하고 있습니다. 업무 자동화에 참고하시면 좋을듯 합니다.

     

     

    유튜브 추천, 구독, 좋아요 꼭 눌러주세요!

    개발자에게 후원하기

    MGtdv7r.png

     

    추천, 구독, 홍보 꼭~ 부탁드립니다.

    여러분의 후원이 빠른 귀농을 가능하게 해줍니다~ 답답한 도시를 벗어나 귀농하고 싶은 개발자~

    감사합니다~

    • 네이버 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 카카오스토리 공유하기
    추천0 비추천0

    댓글목록

    등록된 댓글이 없습니다.