【上級プロ向け】COMオブジェクトの参照リークとゾンビプロセスの完全撲滅!巨大なCDRファイルを安全に連続バッチ処理する堅牢なエラーハンドリング
CorelDRAW VBAを用いた大規模なDTP自動化。その最大の壁は、構文エラーでもファイル破損でもない。「100ファイルを超えたあたりで突然CorelDRAWがフリーズする、あるいはタスクマネージャーの裏で`CorelDRW.exe`がゾンビ化し、メモリを食らい潰していく現象」だ。
ExcelやWordのVBAであれば、`Set app = Nothing` と書いておけばガベージコレクションが何とかしてくれると勘違いしているプログラマーが多い。しかし、CorelDRAWの背後にあるCOMアーキテクチャのライフサイクルは、そんなに甘くはない。
今回は、数千点の巨大CDRファイルをノーミスで連続バッチ変換・処理し、システム資源を1バイトたりともリークさせないための「極限のメモリ管理と堅牢なエラーハンドリング」の全貌を解き明かす。
—
1. なぜCorelDRAW VBAはメモリリークを起こすのか?
CorelDRAWのオブジェクトモデルは、強力である反面、COM(Component Object Model)の参照カウンティングの厳格なルールを開発者に突きつける。
- ドットつなぎ(メソッドチェーン)の罠
`ActiveDocument.Pages(1).Layers(“Layer1”).Shapes(1).Color.UniformColor.SetCMYK 0, 100, 100, 0`
このようなコードを書いた瞬間、VBAの裏側では複数の暗黙的なCOMオブジェクトインターフェイス(IDispatch等)が生成されている。これらをローカル変数に落とし込んで明示的に解放しない限り、参照カウントは0にならず、プロセス終了までメモリ上に残り続ける。
- イベントとモーダル・ダイアログの呪縛
バッチ処理中にエラーが発生し、トラップされなかった例外が外側に伝播すると、CorelDRAWのアプリケーションインスタンスが宙ぶらりんの「ゾンビプロセス」と化す。これが連続バッチでPCをハングアップさせる真犯人である。
—
2. ゾンビ撲滅の鉄則:オブジェクト参照の完全隔離と明示的破棄
メモリリークを防ぐための唯一にして最大の防御壁は、「すべてのオブジェクト変数をスコープごとに局所化し、必ず逆順で `Nothing` を代入する」ことだ。
以下に、巨大CDRファイルを安全に開き、処理し、確実に閉じるための実用的なバッチ処理エンジンを示す。
堅牢なバッチ処理プロシージャの設計図
Option Explicit
‘ メインバッチ処理エントリポイント
Sub ExecuteRobustBatchProcess()
Dim sourceFolder As String
Dim targetFolder As String
Dim fileName As String
Dim fso As Object
Dim folderObj As Object
Dim fileObj As Object
‘ パス設定(環境に合わせて変更)
sourceFolder = “C:\CDR_Input\”
targetFolder = “C:\PDF_Output\”
Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(sourceFolder) Then
MsgBox “入力フォルダが存在しません: ” & sourceFolder, vbCritical
Exit Sub
End If
Set folderObj = fso.GetFolder(sourceFolder)
‘ 処理カウンター
Dim successCount As Long: successCount = 0
Dim errorCount As Long: errorCount = 0
Dim startTime As Double
startTime = Timer
‘ ファイルループ
For Each fileObj In folderObj.Files
If LCase(fso.GetExtensionName(fileObj.Name)) = “cdr” Then
‘ 1ファイルごとに完全に独立したスコープ(関数)へ処理を委譲する
If ProcessSingleFile(fileObj.Path, targetFolder) Then
successCount = successCount + 1
Else
errorCount = errorCount + 1
End If
End If
Next fileObj
‘ クリーンアップ
Set fileObj = Nothing
Set folderObj = Nothing
Set fso = Nothing
MsgBox “バッチ処理完了。” & vbCrLf & _
“成功: ” & successCount & ” 件” & vbCrLf & _
“失敗: ” & errorCount & ” 件” & vbCrLf & _
“処理時間: ” & Format(Timer – startTime, “0.00”) & ” 秒”, vbInformation
End Sub
—
3. 単一ファイル処理における「鉄壁のトライ・キャッチ&ファイナリー」
VBAにはC#のような `try-catch-finally` 構文がない。そのため、`On Error GoTo` を駆使した独自の例外安全パターンを構築する必要がある。
特に重要なのは、「エラーが発生しようとも、開いたドキュメントを閉じ、CorelDRAWのインスタンスを確実に解放する」ことだ。
Function ProcessSingleFile(ByVal filePath As String, ByVal outDir As String) As Boolean
Dim cdrApp As Object
Dim cdrDoc As Object
Dim pdfParams As Object
‘ エラーハンドリングの有効化
On Error GoTo ErrorHandler
‘ 1. CorelDRAWインスタンスの新規起動(毎回プロセスを立ち上げることでメモリ肥大化を根絶する)
‘ ※数千ファイルの処理では、インスタンスを流用するより毎回CreateObjectした方が結果的に安定する。
Set cdrApp = CreateObject(“CorelDRAW.Application”)
cdrApp.Visible = False ‘ バックグラウンド実行
cdrApp.Optimization = True ‘ 画面描画やイベントを抑制してパフォーマンスを極限まで引き上げる
cdrApp.EventsEnabled = False
‘ 2. ドキュメントのオープン
Set cdrDoc = cdrApp.OpenDocument(filePath)
‘ — ここに実際のベクター処理・変換ロジックを記述 —
‘ 例: PDFエクスポート処理
Dim outPath As String
outPath = outDir & cdrApp.FileSystem.GetBaseName(filePath) & “.pdf”
Set pdfParams = cdrApp.CreateStructExportOptions
‘ パラメータ設定の省略…
cdrDoc.PublishToPDF outPath
‘ —————————————————-
‘ 3. 正常終了時のクリーンアップ(作成したドキュメントの明示的クローズ)
If Not cdrDoc Is Nothing Then
cdrDoc.Close
Set cdrDoc = Nothing
End If
‘ 4. アプリケーションの終了
If Not cdrApp Is Nothing Then
cdrApp.Optimization = False
cdrApp.EventsEnabled = True
cdrApp.Quit
Set cdrApp = Nothing
End If
ProcessSingleFile = True
Exit Function
ErrorHandler:
‘ 異常発生時のフォールバックおよびログ記録
Debug.Print “Error processing file: ” & filePath & ” | Error ” & Err.Number & “: ” & Err.Description
‘ 例外時であってもオブジェクトを確実に破壊し、ゾンビプロセスを防ぐ
On Error Resume Next
If Not pdfParams Is Nothing Then Set pdfParams = Nothing
If Not cdrDoc Is Nothing Then
cdrDoc.Close False ‘ 変更を破棄して閉じる
Set cdrDoc = Nothing
End If
If Not cdrApp Is Nothing Then
cdrApp.Optimization = False
cdrApp.EventsEnabled = True
cdrApp.Quit
Set cdrApp = Nothing
End If
ProcessSingleFile = False
Exit Function
End Function
—
4. プロフェッショナルのための高度な予防策:Windows APIによるプロセス監視
どれほどコードを厳格に書いても、CorelDRAWのサードパーティ製プラグインのバグや、極端に破損したCDRファイルに起因するネイティブ例外(Access Violation)が発生した場合、VBAの制御圏外でプロセスが固まることがある。
これを完全に制圧するため、常駐型のバッチ制御システムでは、VBAからWindows WMI(Windows Management Instrumentation)やタスクキルコマンドを組み合わせ、一定時間応答がない `CorelDRW.exe` を強制的に刈り取るガーディアン・プロセスを外部(PowerShellやC#/.NETコンソールアプリ)で併用するのが、極限環境における業界標準のアーキテクチャである。
特に大量のCDRファイルを処理する際は、「インスタンスの使い回しを避け、1ファイルごとにプロセスを完全に使い捨てる(Kill & Create)」アプローチこそが、メモリリークを物理的に無効化する最強の解となる。
—
総括
CorelDRAW VBAによる大規模自動化の成否は、APIの知識量ではなく、「COMオブジェクトのライフサイクルに対する強烈なまでの疑心暗鬼」にかかっている。
- すべての変数はスコープを最小限にし、
- 例外発生時も例外なくリソースを解放し、
- 重い処理の裏でメモリが肥大化する前にプロセスごと再起動する。
この鉄の意志をコードに落とし込んだとき、あなたの自動化システムは24時間365日止まることのない、真の「インダストリアル・グレード」へと昇華する。
