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