VBS(WSH)でウィンドのアクティブ化が失敗する原因と解決策

VBS(WSH)でウィンドのアクティブ化が失敗する原因と解決策

VBSでウィンドのアクティブ化が失敗する原因と解決策

今回のVBS系案件で一番悩んだのがコレです。

ECサイトの各モールにログインすると言う仕様があったのですが、VBSでログイン処理+αを組んだのに2店舗目になるとブラウザが最前面に表示されないのです。

IEが悪いのかと思いChromeで実行すると最前面になる。
「え?? じゃぁIEの問題??」
などなど、いろいろと迷走していました。

ブラウザアクティブ化の参考資料

まずは簡単なアクティブ化のコードを記載します。

ウィンドアクティブ化のスクリプト

具体的なスクリプトはこちらをご覧ください。
コードは開いているウィンドをWin32で検索、指定のEXE名があった場合アクティブ化すると言う流れです。

表示されているタブをアクティブにするscript

意外と簡単ですよね。
でも、私はここでハマったのです。

理由はアクティブにならない理由をコードの間違いだと考えてしまった事。
上手くいかない理由が他にあったわけです。

アクティブウィンドが切り替わらない5つの理由

  1. プロセスIDを取得できていない
  2. SETしたオブジェクトを適切に閉じていない
  3. アクティブウィンドの切り替え指示のタイミングが早い
  4. 破棄されずに残っている変数が存在する
  5. ブラウザを Quit で終了していない(^{F4}などで終了している)

コードを色々弄りテストしたところ、この5つが適切に処理されていないとアクティブ化指示を受け付けませんでした。

IEだったらエクスフローラの後ろで開いたままになるので、データ保存等のファイル操作時に不整合な動きをし、場合によっては大切なデータを削除してしまうこともあり得ます。

1つづつ解説していきます。

プロセスIDを取得できていない

これは【 ウィンドアクティブ化のスクリプト 】の組み方に問題があります。
プロセスIDを取っているかは適当な個所で【 MsgBox(intProcID) 】等書き出してみると確認できます。

ここでIDを取得できている場合は、アクティブ化のコード自体に大きな問題はないはずです。
(あくまでも私の経験則ですが)

SETしたオブジェクトを適切に閉じていない

オブジェクトを適切に終了していないとアクティブ化の指示を受けてくれません。

例えば、次の2つを立ち上げたとします。

Set objIE = CreateObject(“InternetExplorer.Application”)
Set objAct = WScript.CreateObject(“WScript.Shell”)

このうち、次のサイトに移る為、一旦 objIE 閉じるとします。

objIE.Quit

objAct はまだ閉じられていません。
この状態で次のIEを開きアクティブ化を指示するとはねられます。

Set objAct = Nothing

としてオブジェクトを閉じた後でアクティブ化を指示するとちゃんと動作してくれます。

アクティブウィンドの切り替え指示のタイミングが早い

私がハマった一番の理由がコレでした。
アクティブになる時とならない時があるなんて場合は真っ先に疑いましょう。

【 objIE.Quit 】を指示してもオブジェクトが直後すぐに終了されているとは限りません。
そして、新規で開いたオブジェクト(この例の場合はIE)が起動操作中でプロセスIDを適切に返してくれないかもしれません。

終了と起動で時間を待つ事。

VBSのウィンドアクティブ化ではこれが肝です。

破棄されずに残っている変数が存在する

メンター達の作成したスクリプトを流用していると勘違いしている事があります。
「ただの変数だと思っていたらオブジェクトとしてSETされていた」とか。

なので、Function内で宣言された変数は(オブジェクトを含め) End Function の前に全て処分しましょう。

Dim 変数名
Set 変数名= Nothing

正確には変数を破棄しなくてもアクティブ化はしてくれます。
でも、この2つはセットと考えて適切に処理すれば無駄な時間を回避できると思います。

ブラウザを Quit で終了していない

objShell.SendKeys( “^{F4}” )

このコードはIEだけでなくアクティブな様々なウィンドを終了してくれます。
エクスフローラであれFTPソフトであれ、何でもです。
理由はWindowsの共通の処理命令である『ALT + F4』をエミュレートしているからです。

でも、こいつで終了した場合なぜかIEのプロセスがタスクリストに残る事があります。
問題は「ことがある」という所で、無くなる事もあるので表に出てくる現象が一律ではありませんでした。

うん、実にめんどくさい。

IEは必ず【 Quit 】で終了しましょう。

まとめ

私がハマったのは2と3のダブルパンチだったからでした。

適切に閉じられていないオブジェクトがあり、これを修正してもアクティブ化が処理出来たり出来なかったり。
「じゃぁ違う所に問題があるのか?」と色々弄るとまたオブジェクトの残骸が出たりなどなど。

1個の長いスクリプトを書いてしまうと、こういった事は十分起こり得ます。

今回の解決の切っ掛けはスクリプトの整理でした。
まとめて書いていたものを機能をFunctionとして吐き出して本筋から呼び出すというスタイルにしました。
そんな改変を行ったところ「ここか!」というパーツが見つかりました。

上手くいかなかったら整理整頓。大事だと痛感しました。