【実務・中級編】【デフォルトプリンター自動変更】WScript.Network と WMI を組み合わせたオフィス環境別印刷先切替 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【デフォルトプリンター自動変更】WScript.Network と WMI を組み合わせたオフィス環境別印刷先切替

開発現場でよくある問い合わせの一つが、「フロアを移動するたびにデフォルトプリンターを手動で切り替えるのが面倒だ」というものだ。特に、ノートPCを持ち歩くモバイルワーカーや、複数拠点を往来する情シス担当者にとって、これは地味ながらストレスフルなルーティンワークである。

今回は、VBScriptとWSH(Windows Script Host)、そしてWMI(Windows Management Instrumentation)を極限までチューニングし、「現在のネットワーク環境(IPアドレス)を自動検知し、最適なプリンターへシームレスに切り替える堅牢なスクリプト」の構築手法を伝授する。

ネット上のコピペコードをそのまま本番環境に投入して沈没したプロジェクトを数多く見てきた。本記事では、プロのアーキテクトとして「なぜその書き方ではエラーで落ちるのか」「どう設計すべきか」の核心をロジカルに解説する。

1. なぜ「力技のプリンター切替」は現場で破綻するのか?

多くのエンジニアがやりがちな失敗は、IPアドレスの取得をサボり、WScript.Networkの`SetDefaultPrinter`メソッドをエラーハンドリング(`On Error Resume Next`の乱用)なしで直叩きすることだ。

実務の現場では、以下の「罠」が常に潜んでいる。
1. ネットワークの遅延・未接続: Wiッシュの接続確立前にスクリプトが走り、プリンターが見つからずにスクリプト自体が異常終了する。
2. プリンター名のタイポ・存在チェックの欠如: 存在しないプリンターを指定してもVBScriptは即座にトラップしにくい。
3. WMIの重さとCOMオブジェクトの解放漏れ: リソースリークを引き起こし、端末の動作を重くする。

これらを完全に克服するため、「IPアドレスの厳密なフィルタリング」「WMIによる堅牢なネットワークアダプタの監視」「例外処理の構造化」を実装したプロダクションコードを提示する。

2. プロダクションコード:環境自動判別プリンター切替スクリプト

以下のコードを `SetDefaultPrinter.vbs` として保存し、ログオンスクリプトやタスクスケジューラ、あるいはデスクトップショートカットとして配置してほしい。

‘ ==============================================================================
‘ Script Name : AutoSwitchDefaultPrinter.vbs
‘ Description : 端末のIPアドレスを動的に検知し、オフィス環境に応じた
‘ デフォルトプリンターを自動設定するエンタープライズ向けスクリプト
‘ Author : Chief System Architect
‘ ==============================================================================

Option Explicit

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

Sub Main()
Dim strIPAddress
Dim objNetwork, colPrinters, i
Dim targetPrinter

‘ 1. 現在の有効なIPアドレスを取得
strIPAddress = GetActiveIPAddress()

If strIPAddress = “” Then
Call WriteLog(“警告: 有効なIPアドレスが取得できませんでした。ネットワーク未接続の可能性があります。”)
Exit Sub
End If

Call WriteLog(“情報: 現在のIPアドレスを検知しました -> ” & strIPAddress)

‘ 2. IPアドレスのセグメントに基づき、宛先プリンターを決定
‘ ※実際の環境に合わせてサブネットやIPプレフィックスを書き換えてください
Select Case True
‘ 本社オフィス第1営業部 (例: 192.168.10.0/24)
Case Left(strIPAddress, 12) = “192.168.10.”
targetPrinter = “\\PRINT-SRV01\HQ-1F-Laser01”

‘ 本社オフィス第2開発部 (例: 192.168.20.0/24)
Case Left(strIPAddress, 12) = “192.168.20.”
targetPrinter = “\\PRINT-SRV01\HQ-2F-Color02”

‘ 大阪支社 (例: 172.16.50.0/24)
Case Left(strIPAddress, 10) = “172.16.50.”
targetPrinter = “\\OSAKA-SRV01\Branch-Printer”

‘ デフォルト(VPN接続時や自宅リモートワーク等)
Case Else
targetPrinter = “Microsoft Print to PDF” ‘ またはローカルのデフォルトプリンター
Call WriteLog(“情報: 該当する社内セグメントではありません。デフォルトを維持します。”)
Exit Sub
End Select

‘ 3. WScript.Network オブジェクトの生成
Set objNetwork = CreateObject(“WScript.Network”)

‘ 4. 接続先プリンターが端末にインストールされているか検証
If Not IsPrinterInstalled(targetPrinter, objNetwork) Then
Call WriteLog(“エラー: 指定されたプリンターがインストールされていません: ” & targetPrinter)
Set objNetwork = Nothing
Exit Sub
End If

‘ 5. デフォルトプリンターの変更実行
On Error Resume Next
objNetwork.SetDefaultPrinter targetPrinter

If Err.Number <> 0 Then
Call WriteLog(“致命的エラー: プリンターの切替に失敗しました (” & Err.Description & “)”)
Err.Clear
Else
Call WriteLog(“成功: デフォルトプリンターを [” & targetPrinter & “] に切り替えました。”)
End If
On Error GoTo 0

‘ クリーンアップ
Set objNetwork = Nothing
‘ End Sub

‘ ——————————————————————————
‘ Function: GetActiveIPAddress
‘ WMI (Win32_NetworkAdapterConfiguration) を使用して、
‘ 実際にIPがバインドされている有効なIPv4アドレスを取得する
‘ ——————————————————————————
Function GetActiveIPAddress()
Dim objWMIService, colAdapters, objAdapter
Dim strIP

strIP = “”

‘ WMIサービスへの接続 (接続タイムアウトや権限エラー対策)
On Error Resume Next
Set objWMIService = GetObject(“winmgmts:\\.\root\cimv2”)
If Err.Number <> 0 Then
GetActiveIPAddress = “”
Exit Function
End If
On Error GoTo 0

‘ IPEnabled = True のアダプタ(有効なネットワークカード)のみを抽出
Set colAdapters = objWMIService.ExecQuery _
(“Select IPAddress From Win32_NetworkAdapterConfiguration Where IPEnabled = True”)

For Each objAdapter in colAdapters
If Not IsNull(objAdapter.IPAddress) Then
Dim i
For i = LBound(objAdapter.IPAddress) To UBound(objAdapter.IPAddress)
‘ IPv4アドレスのみを対象とする(”:”が含まれていないもの)
If InStr(objAdapter.IPAddress(i), “.”) > 0 Then
strIP = objAdapter.IPAddress(i)
Exit For
End If
Next
End If
If strIP <> “” Then Exit For
Next

‘ オブジェクトの明示的な解放
Set colAdapters = Nothing
Set objWMIService = Nothing

GetActiveIPAddress = strIP
End Function

‘ ——————————————————————————
‘ Function: IsPrinterInstalled
‘ 指定されたプリンターがクライアントPCに登録済みかチェックする
‘ ——————————————————————————
Function IsPrinterInstalled(printerName, netObj)
Dim colPrinters, objPrinter, found
found = False

On Error Resume Next
Set colPrinters = netObj.EnumPrinterConnections
If Err.Number <> 0 Then
IsPrinterInstalled = False
Exit Function
End If
On Error GoTo 0

‘ EnumPrinterConnections は [ポート, プリンター名, ポート, プリンター名…] の順で配列を返す
Dim i
For i = 1 To colPrinters.Count – 1 Step 2
If LCase(colPrinters(i)) = LCase(printerName) Then
found = True
Exit For
End If
Next

‘ ローカルプリンター(PDF等)の場合のフォールバック
If Not found Then
If LCase(printerName) = “microsoft print to pdf” Then
found = True
End If
End If

IsPrinterInstalled = found
End Function

‘ ——————————————————————————
‘ Sub: WriteLog
‘ コンソール出力 (WScript.Echo) と イベントログ / ファイル出力を切り分けるラッパー
‘ ——————————————————————————
Sub WriteLog(message)
‘ デバッグ時は WScript.Echo を有効化、バックグラウンド実行時はコメントアウト推奨
‘ WScript.Echo “[” & Now & “] ” & message

‘ 必要に応じてテキストファイルへの出力ロジックをここに実装する
‘ 例: C:\Logs\PrinterSwitch.log への追記など
End Sub

3. アーキテクチャの解説と実務上のポイント

① WMIの選定理由:なぜ `IPConfig` コマンドを叩かないのか?

初心者によくあるアンチパターンとして、`WScript.Shell` の `Run` メソッドで `ipconfig` を叩き、結果をテキストファイルにリダイレクトして `FSO`(FileSystemObject)でパースする手法がある。
これは非常に低速であり、コマンドプロンプトの黒い画面が瞬時にポップアップするためユーザー体験(UX)を著しく損なう。
インフラのプロであれば、WMI (`Win32_NetworkAdapterConfiguration`) をインメモリで直接叩くべきだ。高速かつクリーンに、バックグラウンドで完結する。

② `EnumPrinterConnections` のデータ構造の罠

`WScript.Network` の `EnumPrinterConnections` メソッドは、返り値として「コレクション」を返すように見えて、実態はインデックスが偶数にポート、奇数にプリンター名が格納された平坦な配列構造を持つ。
コード内の `For i = 1 To colPrinters.Count – 1 Step 2` というループ処理は、この仕様の癖を正確に捉えた実装である。ここを理解していないと、「プリンターが存在するのに『インストールされていない』と判定される」という謎のバグに直面することになる。

③ COMオブジェクトのライフサイクル管理

VBScriptはガベージコレクションの挙動が特殊である。スクリプトが肥大化・常駐化する場合、明示的に `Set objNetwork = Nothing` や `Set objWMIService = Nothing` と記述して参照カウンタをデクリメントし、メモリリークを防ぐ配慮がプロとしての最低限の作法だ。

4. 現場への導入と運用自動化のヒント

作成したスクリプトを組織全体に展開する際は、以下のいずれかの方法を推奨する。

1. Active Directory (AD) のログオンスクリプト / グループポリシー (GPO)
ユーザーがドメインに参加しているPCで社内LANに接続した瞬間、バックグラウンドでこのVBScriptを走らせることで、完全に「ゼロ・オペレーション」でプリンターの最適化が完了する。
2. タスクスケジューラによるネットワーク変更トリガー
Windowsのイベントログ(ネットワーク接続イベント)をトリガーにして本スクリプトをサイレント実行(`wscript.exe //B`)させることで、モバイル端末が社内Wi-Fiに切り替わった瞬間にダイナミックにデフォルトプリンターを変更できる。

レガシーな技術と侮られがちなVBScriptだが、OSの深部にダイレクトにアクセスできる軽量かつ強力な武器である。環境に応じた正確なロジックを組み込むことで、現場のヘルプデスク工数を劇的に削減してほしい。

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