[Pywinauto] Windows GUI 프로그램 자동화

도룩·2023년 11월 5일
0

목적

Windows 환경에서 단순 반복 작업 프로그램들의 실행을 자동으로 컨트롤 하기 위함.

환경

python 3.8.16
pywinauto 0.6.8

준비

예시로 CUDA Toolkit 11.8.0 을 pywinauto를 이용해 자동으로 설치해볼 것이다.

먼저 아래 링크에서 CUDA 11.8.0를 다운로드 해야한다.

CUDA 11.8.0 다운로드 링크

설치 관련해서 pywinauto의 함수만 궁금하신 분들은 install_packages.py에서 install_Cuda 함수만 보시면 된다.

Code

# install_packages.py

import os
import time
from pywinauto import application, keyboard

def load_installer(path, title = None):
    app_backend = "uia" if os.path.splitext(path)[1] == ".exe" else "win32"
    app = application.Application(backend = app_backend)
    
    if os.path.splitext(path)[1] == ".bat":
        os.system(path)
    elif app_backend == "uia":
        app.start(path, wait_for_idle = False)
    elif app_backend :
        app.start("msiexec.exe /i " + os.path.join(os.getcwd(), path), wait_for_idle = False)
        time.sleep(2)

    if title == "NVIDIA 설치 프로그램":
        app["Dialog"].child_window(title = "OK", control_type = "Button").wait("enabled", timeout = 10).click()
    
    installer = application.Application(backend = "uia").connect(title = title, timeout = 5)["Dialog"]

    return installer


def report_install(idx, filepath, result:int, msg = None, process_type = "설치"):
    if result == 1:
        print(f"{idx}. {filepath} : {process_type} 완료.", flush = True)
    elif result == 0:
        print(f"{idx}. {filepath} : 이미 {process_type} 되어 있음.", flush = True)
    elif result == -1:
        print(f"{idx}. {filepath} : {process_type} 실패.  message: {msg}", flush = True)
    elif result == 2:
        print(f"{idx}. {filepath} : 미{process_type}.  message: {msg}", flush = True)
    time.sleep(2)
    
    
def install_Cuda(idx, install_info:dict):
    filepath = install_info["path"]; title = install_info["title"]
    installer = load_installer(filepath, title)

    installer.child_window(title="동의 및 계속(A)", control_type="Button").wait("enabled", timeout=600).click()
    installer.child_window(title="다음(N)", control_type="Button").wait("enabled", timeout=10).click()

    if installer.child_window(title = "I understand, and wish to continue the installation regardless.", control_type = "Button").exists(timeout = 2):
        installer.child_window(title = "I understand, and wish to continue the installation regardless.", control_type = "Button").click()
        keyboard.send_keys("n")

    while True:
        if installer.child_window(title="닫기(C)", control_type="Button").exists(timeout = 1):
            if installer.child_window(title="바탕화면에 NVIDIA GeForce Experience 바로가기를 만듭니다", control_type="ListItem").exists():
                installer.child_window(title="바탕화면에 NVIDIA GeForce Experience 바로가기를 만듭니다", control_type="ListItem").click_input(coords = (0, 0))
                installer.child_window(title="NVIDIA GeForce Experience 시작", control_type="ListItem").click_input(coords = (0, 0))

            installer.child_window(title="닫기(C)", control_type="Button").click()
            report_install(idx, filepath, 1)
            break
        else:
            installer.child_window(title="다음(N)", control_type="Button").wait("enabled", timeout=1800).click()

    while True:
        try:
            installer.child_window(title="닫기(C)", control_type="Button").wait("enabled", timeout=1).click()
            report_install(idx, filepath, 1)
            break
        except:
            installer.child_window(title="다음(N)", control_type="Button").wait("enabled", timeout=1800).click()
# Autoinstaller.py

import os
from install_packages import *
import ctypes

install_info_dict = {
    "CUDA": {"path": "cuda_11.8.0_522.06_windows.exe", "title": "NVIDIA 설치 프로그램"},
    }
    
install_dict = {
    "CUDA" : install_Cuda,
    }

def main():
    print("##### Auto-installer #####")
    
    #관리자 권한 여부 확인
    if bool(ctypes.windll.shell32.IsUserAnAdmin()) is False:
        print("관리자 권한으로 실행하세요.")
        return None
    os.system("pause")

    #Install
    for idx, (key, func) in enumerate(install_dict.items(), start = 1):
        try:
            func(idx, install_info_dict[key])
        except KeyboardInterrupt:
            print("사용자 KeyboardInterrupt 설치 중단")
            break
        except:
            report_install(idx, key, -1, '설치 에러')

    print("\n 프로그램 설치 완료!")


if __name__ == "__main__":
    main()
    while True:
        user_input = input("Enter q to quit: ")
        if user_input.lower() == "q":
            break

0개의 댓글