VBScriptでシリアル通信を制する:外部依存を排除した「真の自動化」アーキテクチャ
業務自動化の世界において、多くのエンジニアが「MSComm」などの古のActiveXコントロールのライセンス問題や、64bit環境でのレジストリ登録の泥沼に足を取られる。
しかし、真のアーキテクトはOSの標準機能(WSH)を極限まで使い倒す。今回は、追加コンポーネントを一切インストールせず、Windows標準の `mode` コマンドとファイルシステムI/Oのみで、シリアル機器(RS-232C)からデータを吸い上げる堅牢な自動化手法を伝授する。
—
1. なぜ「modeコマンド + リダイレクト」が最強なのか
多くのエンジニアがサードパーティ製ライブラリを探すのは、シリアル通信を「イベント駆動の複雑な処理」だと勘違いしているからだ。だが、計測機器のデータ収集という文脈においては、「シリアルポートを単なるファイルストリームとして扱う」のが最も低コストかつ高信頼なアプローチである。
Windowsにおいて `COMx` はデバイスファイルとして露出している。これに対して `mode` コマンドで通信パラメータを規定し、標準入出力(`type` やリダイレクト)を組み合わせることで、複雑なハンドシェイクを意識せずにデータをパイプラインとして抽出できる。
—
2. 実装の要諦:堅牢なデータ収集スクリプト
以下に、実務でそのまま運用可能なプロダクション品質のコードを提示する。このコードの肝は、WScript.Shellの `Exec` メソッドによる非同期的なパイプ監視にある。
‘ シリアルデータ自動取得スクリプト
Option Explicit
Dim objShell, objExec, strLine
Dim strPort, strParams, strOutputFile
‘ 設定値
strPort = “COM1”
strParams = “baud=9600 parity=N data=8 stop=1”
strOutputFile = “C:\Data\Measurement_” & Replace(Date, “/”, “”) & “.log”
Set objShell = CreateObject(“WScript.Shell”)
‘ 1. 通信設定の適用 (エラーハンドリングが必須)
If objShell.Run(“mode ” & strPort & “:” & strParams, 0, True) <> 0 Then
WScript.Echo “ERROR: ポート設定に失敗しました。”
WScript.Quit
End If
‘ 2. デバイスからのストリームを読み取る (非同期実行)
‘ typeコマンドでポートを開き、データを標準出力へ垂れ流す
Set objExec = objShell.Exec(“cmd /c type ” & strPort)
‘ 3. データの書き込みと監視ループ
Dim fso, ts
Set fso = CreateObject(“Scripting.FileSystemObject”)
Set ts = fso.OpenTextFile(strOutputFile, 8, True) ‘ 追記モード
WScript.Echo “計測開始… Ctrl+C で停止”
Do While objExec.Status = 0
If Not objExec.StdOut.AtEndOfStream Then
strLine = objExec.StdOut.ReadLine
‘ ログファイルへ書き出し
ts.WriteLine Now & vbTab & strLine
‘ 必要に応じてコンソールにも表示
WScript.Echo strLine
End If
WScript.Sleep 100 ‘ CPU負荷を抑えるためのインターバル
Loop
ts.Close
Set ts = Nothing
Set fso = Nothing
—
3. 現場で生き残るための「鉄則」
コードを動かして満足してはいけない。現場で1年以上無停止運用するために、以下の設計思想を必ず守れ。
- 排他制御の意識:
シリアルポートは一度開かれると他のプロセスからアクセス不能になる。スクリプトが異常終了した際、ポートが「掴まれたまま」になるケースがある。タスクマネージャで `cmd.exe` や `type.exe` が残っていないか監視する運用設計、あるいはPC再起動時のタスクスケジューラでの強制終了処理を組み込むこと。
- ファイル書き込みのバッファリング:
`FileSystemObject` の `OpenTextFile` は軽量だが、頻繁な書き込みはI/Oボトルネックを生む。実務では、メモリ上で数行溜めてから一括書き込みする「リングバッファ」的な実装に昇華させるのが、中級者から上級者への分水嶺だ。
- 通信のタイムアウト監視:
機器がフリーズしてデータが来なくなった場合、上記の `ReadLine` は無限に待機し続ける。`objExec.StdOut.ReadAll` を安易に使わず、タイムアウトを検知するロジックを自作せよ。
—
結論:技術の深淵へ
VBScriptは「古い」のではない。「OSの深層に近い」のだ。
外部ライブラリに頼ることは、他人の書いたブラックボックスに依存することと同義である。`mode` コマンドで通信を制御し、ストリームを読み取るこの手法は、Windowsが存続する限り機能する。
このコードをベースに、君自身の環境に合わせてデータバリデーションやデータベース挿入(ADO経由)のロジックを組み込んでほしい。自動化エンジニアとしての真価は、いかに「足元の環境」を深く理解し、それだけで解を導き出すかにある。
成功を祈る。
