枯れた技術を極限まで使い倒す:WScript.Shellによるシリアル通信の制御と自動化
VBScriptを「過去の遺物」と切り捨てるのは簡単だ。だが、工場や研究室、あるいはレガシーなインフラ環境において、シリアル通信(RS-232C)を伴う計測機器を制御しなければならない時、我々エンジニアには「極限の環境下で動作する堅牢な実装」が求められる。
外部ライブラリ(ActiveX/COMコンポーネント)をインストールする権限がない? そんなことはエンジニアの言い訳に過ぎない。Windowsが標準で備えるコマンドとWScript.Shellのわずかな機能だけで、シリアル通信を掌握する方法を伝授しよう。
1. 原理:なぜ「外部コントロールなし」で可能なのか
シリアル通信をVBScriptで行う際の最大の障壁は、I/Oストリームの扱いだ。通常、MSComm32.ocxのような外部コンポーネントを頼るが、これらはレジストリ依存度が高く、64bit環境でトラブることが多い。
我々が用いる戦略は、Windows標準の `mode` コマンドでポートを初期化し、標準入出力(StdIn/StdOut)へリダイレクトをかける手法だ。`cmd.exe` のパイプラインを `WScript.Shell` の `Exec` メソッドで叩くことで、シリアルポートをファイルストリームとして擬似的に扱うことができる。
2. 実装:堅牢なデータ取得スクリプト
以下に、メモリ効率と例外処理を考慮した、実戦でそのまま使えるプロトタイプを示す。
‘ シリアルポート通信用ラッパー
Option Explicit
Const COM_PORT = “COM1”
Const COM_SETTING = “baud=9600 parity=N data=8 stop=1”
Dim objShell, objExec, strData
Set objShell = CreateObject(“WScript.Shell”)
‘ 1. ポート設定(modeコマンド)
‘ 同期的に実行し、エラーを握りつぶさないことが肝要
If objShell.Run(“mode ” & COM_PORT & “:” & COM_SETTING, 0, True) <> 0 Then
WScript.Echo “ERROR: Port configuration failed.”
WScript.Quit 1
End If
‘ 2. ストリームのオープン
‘ Execを使うことで、プロセスの標準出力を捕捉する
Set objExec = objShell.Exec(“cmd /c type ” & COM_PORT)
‘ 3. データの読み取りループ
‘ メモリリークを防ぐため、オブジェクトの状態を常に監視する
Do While objExec.Status = 0
If Not objExec.Stdout.AtEndOfStream Then
strData = objExec.Stdout.ReadLine
If Len(strData) > 0 Then
WScript.Echo “Received: ” & strData
‘ ここにログ出力やDB書き込み処理を実装
End If
End If
WScript.Sleep 100 ‘ CPU負荷を抑制するためのインターバル
Loop
‘ 4. 後処理:オブジェクトの明示的解放
‘ VBScriptのガベージコレクションを信じすぎるな
Set objExec = Nothing
Set objShell = Nothing
3. シニアエンジニアが意識すべき「極限の知見」
オブジェクトのライフサイクル管理
VBScriptの `Nothing` 代入は単なる儀式ではない。特に `WScript.Shell` のような重いプロセスを扱う場合、`Set obj = Nothing` を忘れることは、長期間稼働する自動化スクリプトにとっての爆弾となる。メモリ確保の痕跡を残さないことが、システム管理者の矜持だ。
「同期」と「非同期」の境界線
`objShell.Run` は同期実行であり、コマンドの完了を待つ。一方で `objShell.Exec` は非同期実行であり、パイプラインを維持する。シリアル機器からのデータは「いつ来るかわからない」非同期なストリームだ。この実装では `AtEndOfStream` をループで監視しているが、通信タイムアウトを考慮するなら、ループ内にタイムスタンプチェックを組み込み、応答がない場合にプロセスを強制終了(`objExec.Terminate`)させるロジックを必ず追加せよ。
Windows API呼び出しの誘惑を断つ
上級者は `WScript.Shell` を飛び越えて `kernel32.dll` の `CreateFile` や `ReadFile` を呼び出そうとするかもしれない。しかし、VBScriptでDLLのポインタ操作を安全に行うのは、いわば「素手で熱した鉄を触る」ようなものだ。
標準の `mode` コマンドで設定を行い、標準入出力経由でデータを吸い上げるこの手法こそが、環境依存を極限まで排除し、保守コストをゼロに近づけるための「正解」である。
最後に:レガシーを愛せ
VBScriptは、死にゆく言語ではない。WindowsというOSが存在する限り、最も低レイヤーで、最も軽快に動作する「管理者のための魔法」であり続ける。
このコードをただコピペするだけでなく、接続機器のプロトコルに合わせて `ReadLine` の先にある解析ロジックを磨き上げてほしい。技術の真髄は、新しい言語を学ぶことではなく、今あるツールを限界まで掘り下げ、その挙動を完全に支配下に置くことにあるのだから。
