PowerShell

面倒なログイン作業をPowerShellで自動化する【PowerShellでIE操作】

あるアメリカの有名企業で働いていた男が、「6年間まったく仕事をせずに給料を貰っていた」という話、ご存じですか?
自動化を活用して6年間ほぼ仕事をしなかったエンジニア、プログラミングを忘れる

もちろんこの逸話の真偽は不明です。
しかし、現実にプログラミングを駆使して自身の業務の大半を自動化しているビジネスマンは少なくありません。

みなさんの日々の業務の中にも、「これ、ロボットが自動でやってくれたらなー」と思うような面倒な作業があるのではないでしょうか?
あなたがプログラミングを学べば、それ全部自動化できますよ!

「でも、そもそも会社のPCにツールなんかインストールできないし…」
「プログラミング言語を学んでも、結局一般企業じゃ使えないなー」

そう思う方も多いでしょう。

ご安心ください!
今回使用するのはPowershellという、WindowsPCなら初めからインストールされているツールだけです!

Powershellを使って、IEの自動操作を行っていきたいと思います。

プログラミング学習に最もおすすめなWindowsPC

もくじ

  1. 今回作成するツール
  2. Powershell実行方法と注意点
  3. PowershellでIEを開く
  4. エラーハンドリング
  5. まとめ

今回作成するツール

今回は、Powershellを使ってIEを操作して、ログインが必要なページにログインする方法を紹介します。
この方法応用すれば、IE上の入力、クリック操作はすべて自動化できます!

ぜひ使ってみてください!

先にコードの全文を貼っておきます。
これをメモ帳などのテキストエディタにコピペして.ps1という拡張子を付けて保存すればスクリプトファイルの完成です。

詳細は以降の項で解説していきます!

$userid = "" #ユーザーID
$userpass = "" #パスワード
$url = "" #ログインページのURL

# シェル
$shell = New-Object -ComObject Shell.Application
# IE
$ie = New-Object -ComObject InternetExplorer.Application
# ブラウザオープン
$ie.Visible = $true
# HWND
$hwnd = $ie.HWND
# URLオープン(キャッシュ無効)
$ie.Navigate($url, 4)

# ここで再度IEを取得 これやらないとページを読み込めない
while ($ie.Document -isnot [mshtml.HTMLDocumentClass]) {
  $ie = $shell.Windows() | ? { $_.HWND -eq $hwnd }
}

#メソッドの再定義 これやらないと、存在しないメソッドみたいなエラーが返ってくる
function OverrideMethod ([mshtml.HTMLDocumentClass]$Document) {
  $doc = $Document | Add-Member -MemberType ScriptMethod -Name "getElementById" -Value {
     param($Id)
     [System.__ComObject].InvokeMember(
         "getElementById",
         [System.Reflection.BindingFlags]::InvokeMethod,
         $null,
         $this,
         $Id
     ) | ? { $_ -ne [System.DBNull]::Value }
  } -Force -PassThru
  $doc | Add-Member -MemberType ScriptMethod -Name "getElementsByClassName" -Value {
     param($ClassName)
     [System.__ComObject].InvokeMember(
         "getElementsByClassName",
         [System.Reflection.BindingFlags]::InvokeMethod,
         $null,
         $this,
         $ClassName
     ) | ? { $_ -ne [System.DBNull]::Value }
  } -Force
  $doc | Add-Member -MemberType ScriptMethod -Name "getElementsByTagName" -Value {
     param($TagName)
     [System.__ComObject].InvokeMember(
         "getElementsByTagName",
         [System.Reflection.BindingFlags]::InvokeMethod,
         $null,
         $this,
         $TagName
     ) | ? { $_ -ne [System.DBNull]::Value }
  } -Force
  return $doc
}

#オーバーライドメソッドを実行し、WEBページの中身を得る
$document = OverrideMethod($ie.Document)

#ページの中から、フォームに割当てられたFieldというクラスを持つ要素を抜き出す
#ログインしたいページによって異なる
#IDが割り当てられている場合は$document.getElementByIdを使った方がよい

#非常に重要なエラーハンドリング
#きちんと変数に情報が格納されたことを確認しないと、無限にエラーが返ってくる
while ($true) {
  $companybox = $document.getElementsByClassName("Field")
  if ($companybox) { break }
  Start-Sleep -Milliseconds 100
}

while ($true) {
  @($companybox)[0].value = $userid
  @($companybox)[1].value = $userpass
  if (@($companybox)[0].value){
    if (@($companybox)[1].value){
      { break }
    }
  }
  Start-Sleep -Milliseconds 100
}

#ログインボタンの取得とクリック
while ($true) {
  $button = $document.getElementById("Login")
  if ($button) { break }
  Start-Sleep -Milliseconds 100
}
$button.click()

Powershell実行方法と注意点

まずはPowershellの実行方法について。
Powershellの基本的な使い方は、以下のサイトがわかりやすいと思います。

PowerShellの使い方

メモ帳などを使って書いたスクリプトを、test.ps1などという名前で保存したら、以下のコマンドで実行することができます。

$> ./test.ps1 テキストファイル.txt

次のパターンの場合こちらのPowershellを実行することができないので注意してください。

1.セキュリティポリシーによってPowershellの実行がブロックされている場合
  実行するとこんなエラーがでます。
  セキュリティ対策ポリシーでPowershellスクリプトの実行が制限されてる場合にこのエラーがでます。

    .\test.ps1 : このシステムではスクリプトの実行が無効になっているため、ファイル C:\dev\test.ps1 を読み込むことができません。
    詳細については、「about_Execution_Policies」(http://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。
    

 解決法:
  管理者権限でPowershellを開いて以下のコマンドを実行すれば解決します。

  $> Set-ExecutionPolicy RemoteSigned
  

これで解決。

PowershellでIEを開く

コードでいうとこの部分です。

$url = "" #ログインページのURL

# シェル
$shell = New-Object -ComObject Shell.Application
# IE
$ie = New-Object -ComObject InternetExplorer.Application

# ブラウザオープン
$ie.Visible = $true
# HWND
$hwnd = $ie.HWND
# URLオープン(キャッシュ無効)
$ie.Navigate($url, 4)

# ここで再度IEを取得 これやらないとページを読み込めない
while ($ie.Document -isnot [mshtml.HTMLDocumentClass]) {
  $ie = $shell.Windows() | ? { $_.HWND -eq $hwnd }
}

$ie = New-Object -ComObject InternetExplorer.Application
の部分で変数にIEを扱うためのオブジェクトを格納しています。

そこからURLでサイトを開くのですが、この後に再度IEの読み込みをしないと正しく情報が格納されません。
要注意です。

エラーハンドリング

かなりパワフルで便利なPowerShellですが、あんまり好きじゃない点としてエラーハンドリングがめんどくさいことが挙げられます。

ちゃんと例外処理を組み込めばいいのかもしれませんが、スクリプトをべた書きすると、前の処理が完全に終わらない状態でも先のスクリプトが実行されてしまいます。
例えば今回のログインスクリプトで言うと、まだページの読み込みが完了していないのにログイン処理を実行しようとしてエラーが返ってくる感じです。

今回は解決法として、以下のスクリプトを実装しました。

while ($true) {
  $companybox = $document.getElementsByClassName("Field")
  if ($companybox) { break }
  Start-Sleep -Milliseconds 100
}

何をしているか簡単にいうと、ちゃんとWEBページの変数に要素が格納されたことを確認するまで、無限ループし続ける処理を実装してます。

シンプルですが、この構文は今後も役に立つかなと思ってます。
処理の完全実行が確認されるまでひたすらループさせる処理ですね。

while ($true) {
  確実に実行させたい処理
  if (ループを抜ける条件) { break }
  Start-Sleep -Milliseconds 100
}

まとめ

今回はPowerShellで面倒なログイン処理を自動化するスクリプトを紹介しました。
PowerShellは非常に便利ですし、書いてて結構楽しいです。

ただいかんせん、エラーハンドリングのめんどくささとITスキルの低い人にとっては扱いづらい点もあり、あんまり配布には向かないのかなと思ってます。
エラー吐いたら無理やり言うこと聞かせないといけないですからね。

使うにはそれなりにエンジニアリングスキルがいるのかもしれません。

ただ、使いこなせたら非常に強力な武器になる確信はありますので、今後も勉強を続けていこうかなと思います。

プログラミング学習に最もおすすめなWindowsPC

COMMENT

メールアドレスが公開されることはありません。