CorelDRAW VBAを掌握する:数千のCDRを溶かす「メモリ・ゾンビ」完全排除のアーキテクチャ
CorelDRAW VBAで数千単位のバッチ処理を行う際、多くのエンジニアが直面する壁は「メモリリークによる強制終了」と「バックグラウンドに残るゾンビプロセス」だ。CorelDRAWのオブジェクトモデルはVBAの標準的なGC(ガベージコレクション)だけでは到底制御しきれない。
これは、COMオブジェクトのライフサイクルをプログラム側で完全に制御しきれていないことが原因である。本稿では、レガシーを極め尽くしたアーキテクトの視点から、この「腐りゆくシステム」を制御下に置くための極限の設計論を説く。
—
1. ゾンビプロセスを生む「暗黙の参照」を断て
VBAにおける最大の悪習は、`ActiveDocument` や `ActivePage` を無造作に使い回すことだ。これらは内部でCOM参照を保持し、ドキュメントを閉じてもメモリ上のポインタが解放されないまま漂流する。
鉄則:オブジェクトは常に明示的なスコープ内で生成し、`Nothing` で解放する。
メモリを汚染させないための定石コード
‘ 悪い例: アプリケーション全体に参照が残る
Set doc = Application.ActiveDocument
‘ 正しい例: 常に親オブジェクトから辿り、ローカルで完結させる
Dim cdrDoc As CorelDRAW.Document
Set cdrDoc = Application.OpenDocument(“C:\path\to\file.cdr”)
‘ … 処理 …
‘ 強制解放の儀式
cdrDoc.Close
Set cdrDoc = Nothing
—
2. 巨大ループにおける「COM参照の蓄積」を撃破する
数千のファイルを連続処理する場合、単に `Close` するだけではメモリは回復しない。Windows APIを併用し、プロセスを「再起動」させる、あるいはプロセスのワーキングセットをクリアする設計が必要だ。
メモリ解放の秘術:APIによるメモリ最適化
VBA標準機能では限界があるため、`psapi.dll` を利用してプロセスのワーキングセットをOSに強制返還させる。
If VBA7 Then
Private Declare PtrSafe Function EmptyWorkingSet Lib “psapi.dll” (ByVal hProcess As LongPtr) As Long
Private Declare PtrSafe Function GetCurrentProcess Lib “kernel32” () As LongPtr
Else
Private Declare Function EmptyWorkingSet Lib “psapi.dll” (ByVal hProcess As Long) As Long
Private Declare Function GetCurrentProcess Lib “kernel32” () As Long
End If
‘ 100ファイルごとのクリーニング用サブルーチン
Public Sub ForceMemoryCleanup()
Call EmptyWorkingSet(GetCurrentProcess())
DoEvents ‘ OSに処理の猶予を与える
End Sub
—
3. 「何千個も処理する」ための堅牢なバッチアーキテクチャ
単一のVBAプロセスで数千個を処理し続けるのは自殺行為だ。メモリ断片化(メモリフラグメンテーション)が必ず発生し、数時間後には必ずクラッシュする。
真の解決策:「メイン・ランチャー」+「子プロセス(CLI)」構成をとる。
1. ランチャー(VBA): ファイルリストを作成し、一つずつCorelDRAWを起動・制御する。
2. ワーカー(VBA/VBS): 1ファイル処理するごとにプロセスを終了させる。
プロセスの寿命を管理する設計パターン
‘ バッチ処理のメインループ
Sub BatchProcessManager(fileList As Collection)
Dim filePath As Variant
Dim i As Long
For Each filePath In fileList
i = i + 1
‘ 10ファイルごとに再起動をかける(安全策)
If i Mod 10 = 0 Then
‘ ここでCorelDRAWを一旦Quitし、再起動するロジックを呼ぶ
Call RestartCorelDrawProcess
End If
Call ProcessSingleFile(filePath)
‘ 毎回の解放を確実に実行
Call ForceMemoryCleanup
Next filePath
End Sub
—
4. 現場で生き残るための最終警告
- DoEventsの魔力と罠: `DoEvents` はGUIの応答性を維持するが、ループ内で多用しすぎるとスタックオーバーフローや予期せぬイベントの再入を招く。処理の「区切り」でのみ使用すること。
- エラーハンドラは脱出路ではない: エラー発生時に `Set obj = Nothing` を呼び出さないハンドラは、メモリリークの最大の温床だ。`On Error GoTo Cleanup` を必ず実装し、`Cleanup:` ラベルで全ての変数を解放せよ。
- バックグラウンド処理の過信: CorelDRAWはUIを持つことを前提としたCOMオブジェクトである。ヘッドレス(UIなし)での高速化には限界がある。無理に隠そうとせず、UIを最小化してリソースを確保するのが最も現実的だ。
結びに代えて
CorelDRAW VBAは、現代の言語のような「お節介な自動メモリ管理」をしてくれない。しかし、だからこそ開発者がハードウェアの息吹を感じながら制御できる面白さがある。
メモリの断片化を恐れず、OSとの対話をコードに落とし込む。その先に、何十時間回しても一切のリークを許さない「鋼鉄のバッチ処理エンジン」が存在する。貴殿のシステムが、明日も止まらずに稼働し続けることを願う。
