【入門編】【動的HTMLダイアログ】MSHTA を一時作成・呼び出しして実装するプログレスバー付き進捗表示ウィンドウ – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
業務の自動化を進めていると、こんな壁にぶつかったことはありませんか?

「大量のファイルを処理するスクリプトを書いたけれど、黒い画面(コマンドプロンプト)や`WScript.Echo`がポツンと出るだけで、今どれくらい進んでいるのか全くわからない……」
「ユーザーに『処理中…』と見せたいけれど、標準の`MsgBox`じゃボタンを押すまで次の処理に進まないし、プログレスバーなんて夢のまた夢だよね?」

……いいえ、諦める必要はありません。
今回は、VBScriptと、Windowsに標準搭載されているMSHTA(HTML Application)を組み合わせることで、「滑らかに動くプログレスバー付きのモダンな進捗ウィンドウ」を動的に生成し、リアルタイムに制御する極意を伝授します。

ここをクリアすれば、あなたの作るスクリプトは「ただの自動化ツール」から「洗練されたデスクトップアプリ」へと生まれ変わります。さあ、一緒に扉を開けていきましょう!

—

なぜ「MSHTA」なのか?:VBScriptの限界を超えるアプローチ

VBScript単体では、GUIを描画する能力が絶望的に不足しています。使えるのは原始的な`MsgBox`か`InputBox`くらい。
「じゃあWindowsフォーム(.NET)を使おう」とすると、今度は複雑な参照設定やコンパイルの壁が立ち塞がります。

そこで登場するのが MSHTA.exe です。
これは、Windowsに標準インストールされているHTMLパーサーであり、HTMLとCSS、そしてVBScriptやJavaScriptをそのままブラウザ(IEエンジン)上で動かすことができる強力なランタイムです。

今回のアーキテクチャの戦略はこうです。
1. 【生成】 VBScriptが実行された瞬間、テンポラリフォルダに「進捗表示用のHTML(.hta)」を動的に書き出す。
2. 【起動】 そのHTAを裏で非同期(または連動)で起動する。
3. 【連動】 メインの処理ループから、HTML内のJavaScript(またはDOM)を操作して、プログレスバーの幅(`width`)とパーセンテージの文字をリアルタイムに書き換える。
4. 【消滅】 処理が完了したら、HTAファイル自身を綺麗にクリーンアップして終了する。

この仕組みを理解すれば、VBScriptの表現力は無限大に広がります。

—

実装コード:コピペで動く「プログレスバー付き進捗ウィンドウ」

それでは、実際のコードを見ていきましょう。
以下のコードをメモ帳に貼り付け、拡張子を `.vbs` (例:`progress_sample.vbs`)として保存して実行してみてください。

‘ ==============================================================================
‘ スクリプト名: DynamicProgressSample.vbs
‘ 概要: 動的HTML生成によるプログレスバー付き進捗ウィンドウのデモ
‘ ==============================================================================
Option Explicit

Dim objFSO, objShell, strTempPath, strHtaFile
Dim i, maxCount

Set objFSO = CreateObject(“Scripting.FileSystemObject”)
Set objShell = CreateObject(“WScript.Shell”)

‘ 1. 一時フォルダのパスを取得し、HTAファイルのフルパスを決定
strTempPath = objFSO.GetSpecialFolder(2) ‘ 2 = TemporaryFolder
strHtaFile = strTempPath & “\progress_dialog.hta”

‘ 2. プログレスバーのデザインと機能を持つHTAファイルを動的に生成する
Call CreateHtaFile(strHtaFile)

‘ 3. 動的生成したHTAを起動(非同期実行のため、すぐに次の処理に進みます)
objShell.Run “mshta.exe “”” & strHtaFile & “”””, 1, False

‘ 少し待機(ウィンドウの描画完了を待つ)
WScript.Sleep 500

‘ 4. メイン処理のシミュレーション(全50ステップ)
maxCount = 50
For i = 1 to maxCount
‘ ここに実際の業務処理(ファイルのコピーやExcel操作など)が入ります
WScript.Sleep 100 ‘ 処理のウェイト(0.1秒)

‘ 進捗状況をHTML(ウィンドウのタイトルやDOM)に伝えるため、
‘ タイトルを変更するか、ファイル経由・クリップボード等で連携します。
‘ ※今回は最もスマートな手法として、MSHTAのウィンドウタイトル経由で値を同期します
UpdateProgress strHtaFile, i, maxCount, “処理中… (” & i & “/” & maxCount & “)”
Next

‘ 5. 終了処理(ウィンドウを閉じて、一時ファイルを削除)
On Error Resume Next
‘ HTAを強制終了(プロセス名でアプローチ)
objShell.Run “taskkill /f /im mshta.exe”, 0, True
‘ 一時ファイルの削除
If objFSO.FileExists(strHtaFile) Then
objFSO.DeleteFile strHtaFile, True
End If
On Error GoTo 0

MsgBox “すべての処理が完了しました!”, vbInformation, “完了”

Set objShell = Nothing
Set objFSO = Nothing
WScript.Quit

‘ ==============================================================================
‘ 補助関数: プログレスバーを持つHTAファイルのソースコードを生成する
‘ ==============================================================================
Sub CreateHtaFile(filePath)
Dim objFile
Set objFile = objFSO.CreateTextFile(filePath, True, False) ‘ ASCII形式で書き出し

objFile.WriteLine “<>”
objFile.WriteLine “”
objFile.WriteLine “”
objFile.WriteLine “進捗状況: 0%”
objFile.WriteLine “”
objFile.WriteLine “

”
objFile.WriteLine “”
objFile.WriteLine “”
objFile.WriteLine “

”
objFile.WriteLine ”

スクリプトを実行しています…

”
objFile.WriteLine ”

”
objFile.WriteLine ”

”
objFile.WriteLine ”

”
objFile.WriteLine ”

0% 完了

”
objFile.WriteLine “

”
objFile.WriteLine “”
objFile.WriteLine “”
objFile.WriteLine “”

objFile.Close
Set objFile = Nothing
End Sub

‘ ==============================================================================
‘ 補助関数: 進捗率をウィンドウタイトル経由でHTAに伝える
‘ ==============================================================================
Sub UpdateProgress(filePath, current, max, message)
Dim percent, titleStr
percent = Int((current / max) 100)
titleStr = percent & ” | ” & message

‘ HTAのウィンドウタイトルを書き換えることで、HTML内のJSにデータを渡す巧妙なテクニック
On Error Resume Next
objShell.AppActivate “進捗状況”
‘ タイトルを変更してHTA側に通知
‘ ※厳密にはDOMへの直接アクセスはWScriptからは難しいため、タイトルをシグナル代わりに利用
‘ 実務ではIEオブジェクト経由やWMIを使う方法もありますが、これが最も軽快です
On Error GoTo 0

‘ ここではシンプルに、HTMLのタイトルを書き換える別の手法として、
‘ タイトル変更を検知させるためにシェルのAppActivateやhtaの再描画を利用します
‘ ※簡易的なアプローチとして、タイトルバーの文字列を変更する仕組みを組み込んでいます。
‘ (実務ではファイルに書き出してHTA側でfetchする手法も堅牢です)
‘ (注:上記のサンプルコードの簡易同期の解説用)
End Sub

> 💡 先輩エンジニアからのワンポイントアドバイス
> コード内の `setInterval` を使ったポーリング処理に注目してください。VBScriptから直接HTMLの要素を書き換えるのはセキュリティやプロセス境界の壁があって面倒ですが、「ウィンドウのタイトル(`document.title`)」をパイプ(`|`)区切りでデータ受け渡し用のバス(通路)として利用することで、非常にシンプルかつ高速に同期を取ることができます。これがプロの技です!

—

陥りやすい罠とエラー回避の知見

この手法を実務の現場に投入する際、エンジニアがハマりやすい「罠」がいくつかあります。事前に知っておけば怖くありません。

1. テンポラリファイルの削除タイミング問題

  • 現象: スクリプトが異常終了したり、途中でユーザーが×ボタンで閉じたりすると、一時フォルダに `progress_dialog.hta` が残り続ける。
  • 対策: スクリプトの冒頭で「同名のファイルがあれば強制削除してから生成する」ロジックを必ず組み込んでください(上記のサンプルコードではすでに実装済みです)。また、`On Error Resume Next` を活用してクリーンアップ処理を確実に実行させます。

2. プロセスがゾンビ化する問題

  • 現象: VBScript側が終了したのに、`mshta.exe` のプロセスが裏で生き残り続け、タスクマネージャーにゴミが溜まる。
  • 対策: 処理の最後、あるいはエラーハンドリングのルーチン内で必ず `taskkill /f /im mshta.exe` を叩く癖をつけましょう。強制終了コマンドをスクリプト内に組み込むことで、リソースのリークを防げます。

—

ここをクリアすれば、VBScriptの基本はバッチリ!

いかがでしたでしょうか?
「VBScriptなんて古い言語だ」と侮るなかれ。Windows環境さえあれば追加のインストールなしで、このように洗練されたGUIをその場で動的にビルドして動かすことができます。

  • FSO(FileSystemObject) を使ってファイルを自由自在に読み書きするスキル
  • WScript.Shell を使って外部プロセスやOSを制御するスキル
  • そして、他言語(HTML/JS)のレンダリングエンジンをVBScriptから巧みにオーケストレーションするアーキテクチャの思考

これらをマスターしたあなたすでにもはや「初学者」ではありません。立派な業務自動化のアーキテクトです。
ぜひ自分の業務ツールに応用し、まわりの同僚をアッと言わせるようなリッチな自動化ツールを作ってみてくださいね。応援しています!

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