[PowerShell]IEで行うログイン処理を自動化する

はじめに

前回、IEでのGUI操作自動化するための前段として、必要な処理の洗い出しと個別の実装を行いました。

今回は、これらの処理を組み合わせて、「IEで行うログイン処理を自動化」してみようと思います。

自動化するIEの操作

自動化対象とした「パスワード認証2回」の具体的な操作は以下の通りです。

  1. IEを起動し、指定のURLを開く。
  2. 画面①にて、ユーザ/パスワードを入力し「ログイン」ボタンを押下する。
  3. 画面②にて、「接続」リンクを押下する。
  4. 画面③のモーダルウィンドウにて、ユーザ/パスワードを入力し「ログイン」ボタンを押下する。

自動化対象WebサイトのHTML構造解析

ボタンや入力欄を取得するため、HTML構造を整理します。

  1. 画面①は単純な1枚構造
  2. 画面②はFrame構造となっていて、frame(0)に押下したいリンクが存在する。
  3. 画面③はFrame構造かつiFrameが使われていて、frame(0)モーダルウィンドウ<iframe id=”irame01″>が表示され、その中に入力欄/ボタンが存在する。

ソースコード

前回実装した個別の処理を組み合わせて、上記3画面の遷移手順を実装していきます。

login.ps1

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName Microsoft.VisualBasic

# 引数0:画面①のユーザー
# 引数1:画面①のパスワード
# 引数2:画面③のユーザー
# 引数3:画面③のパスワード

# シェルを取得
$shell = New-Object -ComObject Shell.Application

# IEオブジェクト
$ie = New-Object -ComObject InternetExplorer.Application;


# URL指定してIEを開く
$URL = "https://www.hogehoge.com/login/"
$ie.Visible = $true
$ie.Navigate($URL)

# IEをアクティブにする
$window_process = Get-Process -Name "iexplore" | ? {$_.MainWindowHandle -eq $ie.HWND}
[Microsoft.VisualBasic.Interaction]::AppActivate($window_process.ID) | Out-Null

####画面1
# ログインボタンが表示されるまで待機
while ($true) {
    $doc = $ie.Document
    $button = [System.__ComObject].InvokeMember("getElementById",[System.Reflection.BindingFlags]::InvokeMethod, $null, $doc, @( "button01" ))

    # 表示された
    if ($button -ne [System.DBNull]::Value) {
        Write-Host "got button"
        break
    }

    Write-Host "--- searching for button ---"
    Start-Sleep -Milliseconds 500
}

# ユーザーを入力
$input = [System.__ComObject].InvokeMember("getElementById",[System.Reflection.BindingFlags]::InvokeMethod, $null, $doc, @( "user01" ))
$input.focus()
#[System.Windows.Forms.SendKeys]::SendWait($Args[0])
$input.value=$Args[0]

while ($input.value -ne $Args[0]) {
    Start-Sleep -Milliseconds 500
}

# パスワードを入力
$input = [System.__ComObject].InvokeMember("getElementById",[System.Reflection.BindingFlags]::InvokeMethod, $null, $doc, @( "password01" ))
$input.focus()
#[System.Windows.Forms.SendKeys]::SendWait($Args[1])
$input.value=$Args[1]

while ($input.value -ne $Args[1]) {
    Start-Sleep -Milliseconds 500
}

# ログインボタン押下
$button.click()

####画面2
# リンクが表示されるまで待機
while ($true) {

    # frame(0)を取得する
    $frames = $ie.document.frames
    $doc = $frames.item(0).document

    # frame(0)内のリンクタグを取得する
    $link = [System.__ComObject].InvokeMember("getElementById",[System.Reflection.BindingFlags]::InvokeMethod, $null, $doc, @( "link01" ))

    # 表示された
    if ($link -ne [System.DBNull]::Value) {
        Write-Host "got link"
        break
    }
    Write-Host "--- searching for link ---"
    Start-Sleep -Milliseconds 500
}

# リンク押下
$link.click()

####画面3
# モーダルウィンドウ表示まで待機
while ($true) {

    # frame(0)を取得する
    $frames = $ie.document.frames
    $if0 = $frames.item(0).document

    # frame(0)内のiframeタグを取得する
    $iframe = [System.__ComObject].InvokeMember("getElementById",[System.Reflection.BindingFlags]::InvokeMethod, $null, $if0, @( "iframe01" ))

    # 表示された
    if ($iframe -ne [System.DBNull]::Value) {
        Write-Host "got iframe"
        break
    }

    Write-Host "--- searching for iframe ---"
    Start-Sleep -Milliseconds 500
}

# ログインボタン表示まで待機
while ($true) {

    # iframeタグ内のボタンを取得する
    $ifameDoc = $iframe.contentWindow.document
    $button = [System.__ComObject].InvokeMember("getElementById",[System.Reflection.BindingFlags]::InvokeMethod, $null, $ifameDoc, @( "button02" ))

    # 表示された
    if ($button -ne [System.DBNull]::Value) {
        Write-Host "got button"
        break
    }

    Write-Host "--- searching for button ---"
    Start-Sleep -Milliseconds 500
}

# ユーザーを入力
$input = [System.__ComObject].InvokeMember("getElementById",[System.Reflection.BindingFlags]::InvokeMethod, $null, $ifameDoc, @( "user02" ))
$input.focus()
#[System.Windows.Forms.SendKeys]::SendWait($Args[2])
$input.value=$Args[2]

while ($input.value -ne $Args[2]) {
    Start-Sleep -Milliseconds 500
}

# パスワードを入力
$input = [System.__ComObject].InvokeMember("getElementById",[System.Reflection.BindingFlags]::InvokeMethod, $null, $ifameDoc, @( "password02" ))
$input.focus()
#[System.Windows.Forms.SendKeys]::SendWait($Args[3])
$input.value=$Args[3]

while ($input.value -ne $Args[3]) {
    Start-Sleep -Milliseconds 500
}

# ログオンボタン押下
$button.click()

基本的な処理の流れは3画面とも、押下したいボタン/リンクが表示されるまでタグ検索を繰り返し、見つかったら入力欄に値を入力して、ボタン/リンクを押下します。

ポイント

3画面目のモーダルウィンドウは、画面遷移後にスクリプト非同期表示しているようで、画面遷移直後だと<ifame>タグを取得できないことがあります。
そのため、まず<iframe>タグの検索を繰り返し、<iframe>タグが取得出来たらその中のタグの検索をする2段構造にしています。

実行方法

コマンドライン

Windowsコマンドプロンプトで以下のコマンドを実行します。

powershell -NoProfile -ExecutionPolicy Unrestricted .\login.ps1 user01 password01 user02 password02
  • user01 : 画面①のユーザー
  • password01: 画面①のパスワード
  • user02: 画面③のユーザー
  • password02: 画面③のパスワード

Windowsバッチ

login.ps1と以下の2ファイルを同じフォルダに格納し、login.batをダブルクリックします。

AuthInfo.dat

############################################################
# 画面①認証情報
############################################################
# ユーザー1
user01
# パスワード1
password01
#
############################################################
# 画面③認証情報
############################################################
# ユーザー2
user02
# パスワード2
password02
#

login.bat

@echo off
@setlocal enabledelayedexpansion

echo --AuthInfo.dat読み込み中--

set psArgs=
for /f "eol=#" %%i in (AuthInfo.dat) do (

    set temp="%%i"
    set psArgs=!psArgs! !temp!
)

echo --AuthInfo.dat読み込み完了--

echo --自動ログインシェル実行中--

powershell -NoProfile -ExecutionPolicy Unrestricted .\login.ps1%psArgs%

echo --自動ログインシェル実行完了--

Windowsバッチ(login.bat)が認証情報(AuthInfo.dat)を読み込み、login.ps1のパラメータに設定して実行します。

コメント

タイトルとURLをコピーしました