SolidWorks APIの深淵:堅牢な例外処理による「死なない」自動化アーキテクチャの構築
SolidWorksの自動化において、最も忌むべきは「マクロが沈黙し、プロセスがゾンビ化すること」だ。
数時間かかる大規模アセンブリのバッチ処理の最中、最後の一手で予期せぬAPI例外が発生し、SOLIDWORKSのプロセスがメモリ上に居座り続ける……。そんな惨劇を繰り返してはならない。
私は長年、数百万行規模のCAD自動化コードを保守してきたが、結論は一つだ。「エラーは発生するもの」という前提で、プロセスを保護し、トレーサビリティを確保するトランザクション的ロギングを実装せよ。
今回は、VBAの脆弱なエラーハンドリングを「堅牢な防壁」へと昇華させるための極限の知見を授ける。
—
1. 脆弱なエラーハンドリングの根絶
多くのエンジニアは `On Error Resume Next` を乱用する。これは百害あって一利なしだ。エラーを握りつぶせば、不整合なメモリ状態のまま処理が継続し、結果として不正なCADデータが生成される。
我々が求めるのは、「エラーを捕捉し、スタックトレースを記録し、安全に退避する」仕組みである。
堅牢なエラーハンドリング・テンプレート
以下に、私が設計するマクロの基本構造を提示する。これは、`SldWorks`と`ModelDoc2`のオブジェクトライフサイクルを意識した構造だ。
‘ ———————————————————
‘ 堅牢なマクロ実行のテンプレート
‘ ———————————————————
Public Sub ExecuteAutomatedTask()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
‘ エラーハンドラの設定
On Error GoTo ErrorHandler
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
‘ ここにメインのロジックを記述する
Call ProcessModel(swModel)
CleanUp:
‘ 終了時のメモリ解放(重要:COMオブジェクトの明示的破棄)
Set swModel = Nothing
Set swApp = Nothing
Exit Sub
ErrorHandler:
‘ 致命的なエラーの記録
Call LogError(Err.Number, Err.Description, “MainProc”)
‘ ユーザーへの警告とプロセスの安全な停止
MsgBox “致命的なエラーが発生しました。詳細はログを確認してください。”, vbCritical
Resume CleanUp
End Sub
—
2. トランザクション風エラーロギングの極意
エラーが発生した際、単に「エラーが出た」と記録しても意味はない。「どのモジュールで、どのプロシージャで、どのファイルが」失敗したのか。この情報をCSVへ追記する。
CSVロギングの実装
Public Sub LogError(ByVal errNum As Long, ByVal errDesc As String, ByVal procName As String)
Dim logPath As String
Dim fileNum As Integer
logPath = Environ(“USERPROFILE”) & “\Desktop\SolidWorks_ErrorLog.csv”
fileNum = FreeFile
‘ CSVへの追記処理
Open logPath For Append As #fileNum
Print #fileNum, Now & “,” & procName & “,” & errNum & “,” & errDesc & “,” & Application.ActiveDocument.GetPathName
Close #fileNum
End Sub
このログを溜めることで、特定のファイル構造においてのみ発生する「エッジケースなバグ」を統計的にあぶり出すことが可能になる。
—
3. シニアレベルの知見:メモリ最適化とプロセス管理
オブジェクトの明示的解放(Disposeの精神)
VBAはガベージコレクションを信用してはならない。特にSolidWorks APIのCOMオブジェクトは、明示的に `Nothing` を代入しない限り、循環参照やメモリリークを引き起こす。
特にループ処理内で `GetFeatureByName` や `GetFirstFeature` を多用する場合、ループの各イテレーションで生成されるオブジェクトを必ず解放せよ。
Windows APIによる「フリーズ」の監視
SolidWorksが応答なしになった場合、VBA側からは何もできない。これを防ぐには、Windows APIの `SendMessage` を駆使し、バックグラウンドでウォッチドッグタイマー的な役割を果たすプロセスを常駐させるアーキテクチャが最も堅牢だ。
以下は、プロセスがフリーズした際に強制終了を検討する際の一助となる、プロセスID取得のヒントである。
‘ 現在のSolidWorksプロセスのIDを取得
Private Declare PtrSafe Function GetCurrentProcessId Lib “kernel32” () As Long
—
チーフアーキテクトからの提言
システム管理者の立場にある読者へ。
自動化コードにおいて、「正常系」をコード化するのはジュニアエンジニアの仕事だ。シニアの仕事は「異常系」をどれだけ完璧に制御下に置くかにある。
1. 疎結合なモジュール設計: メインロジックとロギングは分離せよ。
2. 型指定の厳格化: `Variant` 型は悪だ。`SldWorks.ModelDoc2` 等、明示的な型指定がAPIコールのオーバーヘッドを削減する。
3. 継続的インテグレーション: エラーログCSVを週次で集計し、マクロの「劣化」を定量的に測定せよ。
コードは、一度書いて終わりではない。SOLIDWORKSという巨大で複雑な生命体と対話するための、敬意ある作法としてコードを書き上げること。それこそが、伝説的なエンジニアの流儀である。
何かあれば、また聞きに来るといい。貴殿の自動化が、静寂の中で完璧に遂行されることを期待している。
