0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GlobalProtect VPN の接続自動化

0
Posted at

GlobalProtect VPN の接続自動化 します

毎回毎回入力するのが嫌になってきたので

接続画面を呼び出して、 .env ファイルに記載のユーザとパスを利用して自動接続してくれます。

connect_vpn.py
import os
import sys
import time
import subprocess
import pyautogui
import pyperclip
from dotenv import load_dotenv

# UI Automation 関連のインポート
import comtypes
from comtypes import CoCreateInstance
import comtypes.client

# UIAutomationCore.dll の読み込み
comtypes.client.GetModule('UIAutomationCore.dll')
from comtypes.gen.UIAutomationClient import *

###=============================================================================
### 設定・定数
###=============================================================================
GP_EXE_PATH = r"C:\Program Files\Palo Alto Networks\GlobalProtect\PanGPA.exe"
DEFAULT_TIMEOUT = 60  # 要素検知のデフォルトタイムアウト(秒)

###=============================================================================
### 共通:要素待機関数
###=============================================================================

def wait_for_element(automation_id, label, timeout=DEFAULT_TIMEOUT):
    """
    指定したIDの要素が出現するまで待機する。見つかれば要素を返し、なければNoneを返す。
    """
    print(f"  > {label} を待機中...")
    time.sleep(2) 
    condition = uia.CreatePropertyCondition(UIA_AutomationIdPropertyId, automation_id)
    
    start_time = time.time()
    while time.time() - start_time < timeout:
        element = window.FindFirst(TreeScope_Descendants, condition)
        if element:
            return element
        time.sleep(0.5)  # 0.5秒間隔でチェック
    
    return None


###=============================================================================
### 関数定義
###=============================================================================

def click_and_type(automation_id, text, label):
    """
    要素を検知してからクリックし、クリップボード経由でテキストを入力する。
    """
    element = wait_for_element(automation_id, label)
    
    if element:
        rect = element.CurrentBoundingRectangle
        cx = (rect.left + rect.right) // 2
        cy = (rect.top + rect.bottom) // 2
        
        pyautogui.click(cx, cy)
        time.sleep(0.3)
        
        # 全選択して上書き
        pyautogui.hotkey('ctrl', 'a')
        pyautogui.press('backspace')
        
        pyperclip.copy(text)
        pyautogui.hotkey('ctrl', 'v')
        
        print(f"  [OK] {label} を入力しました。")
        return True
    else:
        print(f"  [!] エラー: {label} がタイムアウト内に見つかりませんでした。")
        return False


def click_button(automation_id, label):
    """
    ボタンを検知してから、マウス移動+フォーカス+Enterで押下する。
    """
    button = wait_for_element(automation_id, label)

    if not button:
        print(f"  [!] エラー: {label} が見つかりませんでした。")
        sys.exit(-1)
    
    rect = button.CurrentBoundingRectangle
    cx = (rect.left + rect.right) // 2
    cy = (rect.top + rect.bottom) // 2
    
    pyautogui.moveTo(cx, cy, duration=0.5)
    button.SetFocus()
    time.sleep(0.2)
    pyautogui.press('enter')
    
    print(f"  [OK] {label} をクリックしました。")


def connect_check(retry_count):
    """
    接続完了テキスト(ID:1165)が表示されるまでループ待機する。
    """
    print("\n接続完了を待機しています...")
    time.sleep(1)
    is_connected = False

    for i in range(retry_count):
        status_cond = uia.CreatePropertyCondition(UIA_AutomationIdPropertyId, "1165")
        status_element = window.FindFirst(TreeScope_Descendants, status_cond)
        
        if status_element:
            # 「接続済み」という文字列を確認
            if status_element.CurrentName == "接続済み":
                print(f"\n[成功] ステータスが '{status_element.CurrentName}' になりました。")
                is_connected = True
                break
                
        # 経過表示
        print(f"待機中... ({i+1}/{retry_count})", end="\r")
        time.sleep(1)
    
    if is_connected:
        print("\n" + "="*40)
        print(" VPN接続が正常に完了しました。")
        print("="*40)
    else:
        print("\n" + "!"*40)
        print(" タイムアウト: 接続済みを確認できませんでした。")
        print("!"*40)
        sys.exit(1)


###=============================================================================
### メイン処理開始
###=============================================================================

load_dotenv()
USERNAME = os.getenv("GP_USERNAME")
PASSWORD = os.getenv("GP_PASSWORD")

if not USERNAME or not PASSWORD:
    print("エラー: .env から認証情報を取得できません。")
    sys.exit(1)

# 1. アプリ起動
if os.path.exists(GP_EXE_PATH):
    subprocess.Popen(GP_EXE_PATH)
    print("GlobalProtect 画面を呼び出しています...")
else:
    sys.exit(-1)

# 2. UIA初期化
uia = CoCreateInstance(
    CUIAutomation._reg_clsid_, 
    interface=IUIAutomation, 
    clsctx=comtypes.CLSCTX_INPROC_SERVER | comtypes.CLSCTX_LOCAL_SERVER
)
root_element = uia.GetRootElement()

# 3. ウィンドウ検知ループ(起動に時間がかかる場合を考慮)
print("ウィンドウを探しています...")
win_condition = uia.CreatePropertyCondition(UIA_NamePropertyId, "GlobalProtect")
window = None
for _ in range(120): # 最大10秒待機
    window = root_element.FindFirst(TreeScope_Children, win_condition)
    if window: break
    time.sleep(0.5)

if not window:
    print("エラー: ウィンドウが見つかりません。")
    sys.exit(-1)

# 4. 操作シーケンス(ここから各要素の出現を待って進む)
print("\n--- 自動操作開始 ---")

# ステップ1: 最初の接続ボタン
click_button("1160", "最初の接続ボタン")

# ステップ2: ログイン入力(ID 1166 が出るまで待つ)
if not click_and_type("1166", USERNAME, "ユーザ名入力欄"):
    sys.exit(-1)

# ステップ3: パスワード入力
click_and_type("1167", PASSWORD, "パスワード入力欄")

# ステップ4: 最終接続ボタン
click_button("1168", "確定接続ボタン")

# ステップ5: 完了確認(最大60秒)
connect_check(120)

print("\n10秒後に終了します。")
time.sleep(10)
sys.exit(0)

これを BAT で呼び出して自動化完成

connect_vpn.bat
@echo off
setlocal
:: 文字コードをUTF-8に設定
chcp 65001 > nul

:: スクリプトがあるディレクトリに移動
cd /d "%~dp0"

echo ==========================================
echo   GlobalProtect VPN 接続スクリプト起動
echo ==========================================

:: Pythonを実行(pythonにパスが通っている前提)
:: 必要に応じて python を "C:\Path\To\python.exe" のようにフルパスで記述してください
python connect_vpn.py

:: エラーが起きた場合は画面を止め、正常終了なら自動で閉じる(お好みでpauseを消してください)
if %errorlevel% neq 0 (
    echo.
    echo [!] スクリプトが異常終了しました。
    pause
) else (
    echo [OK] プロセスが完了しました。
    timeout /t 5
)

endlocal
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?