【実務・中級編】【ドキュメントサイレント印刷】Shell.Application の InvokeVerb を用いたPDF・Wordファイルのバックグラウンド一括印刷 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

VBScriptを掌握する極限の知見:Shell.Application.InvokeVerbによるドキュメントサイレント印刷の極意

開発現場でふと理不尽な要求につきつけられることはないか?
「毎朝出社するまでに、前日分のPDFやWord、Excelファイル数十枚を自動でプリンターに出力してほしい。もちろん、プレビュー画面やアプリのGUIなんてユーザーに見せちゃダメだ。一瞬で裏で終わらせてくれ」

……レガシーなWindows環境において、この要件をまともにやろうとすると地獄を見る。各アプリケーション(Acrobat, Word, Excelなど)のCOMオブジェクトを個別に起動し、`Visible = False` を設定し、`PrintOut` メソッドを叩く。一見正しく思えるこのアプローチは、実務では「プロセスリーク」「ハングアップ」「ダイアログの裏画面モーダル停止」の三冠王を引き起こす。特にAdobe AcrobatのCOM制御の不安定さは、夜間バッチを確実に死に至らしめる悪夢の元凶だ。

だが、思い出してほしい。我々にはWindowsシェルという最強にして最古の隠し剣がある。
今回は、`Shell.Application` の `InvokeVerb` を駆使し、GUIの影に隠れてドキュメントを完全サイレントで一括屠る、極限まで洗練されたVBScript自動化アーキテクチャを伝授しよう。

1. なぜ「個別のCOM制御」は現場で破綻するのか?

多くの初学者は、Wordなら `Word.Application`、PDFなら `Acrobat.Application` をコードから立ち上げようとする。しかし、エンタープライズの現場でこれをやると以下の壁に阻まれる。

1. アプリケーションごとの実装差異:PDF、Word、Excel、テキストファイルでは印刷を指示するAPIが完全にバラバラ。コードが肥大化し、保守性がゼロになる。
2. ゾンビプロセスの嵐:エラーハンドリングを少しでもミスると、タスクマネージャーに `EXCEL.EXE` や `AcroRd32.exe` が亡霊のように居座り続け、メモリを食いつぶす。
3. 印刷ダイアログの幽霊(モーダルブロック):プリンタードライバの仕様やファイル破損により、バックグラウンドのハズが「プリンターを選択してください」といったダイアログが裏画面でポップアップし、スクリプトが永遠にフリーズする。

解決策:OSの「関連付け印刷(Shell Verb)」の利用

Windowsのエクスプローラーでファイルを右クリックすると「印刷」というメニューがある。あれの本質は、OSがファイルの拡張子関連付けを解釈し、背後でアプリケーションに印刷命令(`print` 動詞)を投げる仕組みだ。
この挙動をプログラムから擬似的に、かつ完全に非表示(サイレント)で実行するのが `Shell.Application` の `InvokeVerb(“print”)` である。

2. アーキテクチャ設計上の注意点と罠

この手法はエレガントだが、VBScript特有の「非同期処理の罠」を理解していないと痛い目をみる。

  • `InvokeVerb` は非同期である

`InvokeVerb` を呼ぶと、OSは瞬時に「印刷プロセスへの指示」を完了し、制御をVBScript側に返す。つまり、ループを回して一斉に100個のファイルを `InvokeVerb` すると、アプリケーションが100個同時に立ち上がり、メモリが爆発してプリンターがパニックを起こす。

  • ウェイト(待機時間)の科学

各ファイルの処理の間には、適切なスリープ(インターバル)と、プロセス競合を防ぐための堅牢なエラーハンドリングが不可欠である。

3. プロダクションコード:完全サイレント一括印刷スクリプト

以下のコードは、指定したフォルダ内の対象拡張子ファイル(PDF, DOC, DOCX, XLS, XLSX, TXTなど)を検出し、OSのシェル動詞を利用してバックグラウンドで安全に連続印刷する、実戦投入仕様のVBScriptである。

メモ帳に貼り付け、拡張子を `.vbs` (例: `SilentPrint.vbs`)として保存して使用してほしい。

‘ ==============================================================================
‘ Script Name : SilentDocumentPrinter.vbs
‘ Description : Shell.Application InvokeVerbを用いたドキュメントのサイレント一括印刷
‘ Author : チーフアーキテクト
‘ ==============================================================================
Option Explicit

‘ — 設定エリア —
‘ 印刷対象のファイルが格納されているフォルダパス(末尾のバックスラッシュに注意)
Const TARGET_FOLDER = “C:\PrintQueue\”
‘ 印刷処理後のファイル待機時間(ミリ秒)。プリンターのバッファ溢れとアプリの多重起動を防止
Const PRINT_INTERVAL_MS = 3500
‘ ——————

Sub Main()
Dim objFSO, objShell, targetFolderObj, fileItem
Dim ext, shellFolder, shellFile
Dim fCount

fCount = 0

‘ オブジェクトの生成
Set objFSO = CreateObject(“Scripting.FileSystemObject”)
Set objShell = CreateObject(“Shell.Application”)

‘ フォルダの存在確認
If Not objFSO.FolderExists(TARGET_FOLDER) Then
WScript.Echo “エラー: 指定されたフォルダが存在しません -> ” & TARGET_FOLDER
Exit Sub
End If

Set targetFolderObj = objFSO.GetFolder(TARGET_FOLDER)

‘ フォルダ内のファイルを走査
For Each fileItem in targetFolderObj.Files
ext = LCase(objFSO.GetExtensionName(fileItem.Name))

‘ 印刷を許可する拡張子ホワイトリスト(必要に応じて追加・削除)
Select Case ext
Case “pdf”, “doc”, “docx”, “xls”, “xlsx”, “txt”, “csv”
WScript.Echo “印刷処理中: ” & fileItem.Name

‘ Shell.Applicationを通じて名前空間経由でファイルオブジェクトを取得
Set shellFolder = objShell.NameSpace(targetFolderObj.Path)
Set shellFile = shellFolder.ParseName(fileItem.Name)

If Not shellFile Is Nothing Then
‘ “print” 動詞(Verb)を非表示(拡張子関連付けのデフォルト動作)で実行
‘ 引数の “printto” が使える場合はプリンター指定も可能だが、
‘ 標準の “print” は規定のプリンターへサイレント(または最小限のUI)で送出される
shellFile.InvokeVerb(“print”)

fCount = fCount + 1

‘ ハングアップ・プリンターのスプール詰まりを防ぐための物理ウェイト
WScript.Sleep PRINT_INTERVAL_MS
End If

‘ オブジェクトのメモリ解放(VBScriptのスコープリーク対策)
Set shellFile = Nothing
Set shellFolder = Nothing

Case Else
‘ 対象外の拡張子はスキップ
End Select
Next

‘ クリーンアップ
Set targetFolderObj = Nothing
Set objShell = Nothing
Set objFSO = Nothing

WScript.Echo “処理完了: 合計 ” & fCount & ” 件のドキュメントを印刷キューに送信しました。”
End Sub

‘ メイン処理の実行
Main()

4. このコードが「プロの仕事」である理由(技術的解説)

1. ホワイトリスト方式の拡張子判定
`Select Case ext` を用いることで、Thumbs.dbやデスクトップ設定ファイルなどのゴミファイルが誤って印刷される事故を未然に防ぐ。
2. メモリとCOMの適切な解放
VBScriptでは参照したCOMオブジェクトを放置するとガベージコレクションが遅れ、プロセスが残る原因になる。ループの都度 `Set shellFile = Nothing` を明示し、ライフサイクルを完全に制御している。
3. 絶妙なスプレッド(`WScript.Sleep`)
`PRINT_INTERVAL_MS = 3500` (3.5秒)は、OfficeアプリケーションやAcrobatが起動し、バックグラウンドで印刷命令をプリンタースプーラーに流し込んでから安全に終了するまでの「黄金の時間」だ。現場のプリンター性能やドキュメントの平均サイズに合わせて、この値はチューニングしてほしい。

5. チーフアーキテクトからの最後のアドバイス

このスクリプトをWindowsの「タスクスケジューラ」に組み込み、特定のフォルダを監視(あるいは定時実行)させることで、完全無人の帳票・ドキュメント自動印刷ラインが完成する。

VBScriptは「古い言語」と揶揄されることもあるが、OSの根幹(シェル)と直接対話できるこの類まれな機動力は、現代のモダンな言語(PythonやPowerShellなど)であっても、重厚長大なライブラリを入れなければ実現できない領域をいとも簡単に突破する。
道具の特性を深く理解し、手綱をしっかりと握りしめろ。現場の自動化において、君のコードは最大の武器となるはずだ。

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