【実務・中級編】【上級者】VBAからWindowsのCOMオブジェクト(WMI)を利用してローカルマシンのCPUおよびメモリ負荷を常時監視し、過負荷時はPDF変換プロセスを自動スロットリング(遅延制御)する堅牢スクリプト – PowerPoint VBA解析バイブル

スポンサーリンク

限界を超えた自動化:VBAによる「CPU負荷連動型」PDFバッチ処理アーキテクチャ

業務自動化の現場でよくある失敗、それは「PCのリソースを無視した無慈悲なループ処理」だ。数百のPowerPointファイルを一括でPDF変換する際、VBAが全力でCPUを回せば、仮想デスクトップ(VDI)環境では瞬く間にフリーズし、共有サーバーでは管理者からログオフを命じられることになる。

真の自動化エンジニアは、プログラムを「速く」動かすことではなく、「OSの呼吸を乱さず、最も効率的に完遂させる」ことに知見を傾ける。今日は、WindowsのWMI(Windows Management Instrumentation)を叩き、CPU負荷を監視しながらPDF変換の「スロットリング(流量制御)」を行う、プロダクションレベルのアーキテクチャを伝授する。

—

1. なぜ「力任せのループ」が破滅を招くのか

VBAで `Presentation.SaveAs` を連続実行すると、PowerPointのバックエンドプロセスはメモリとCPUを極限まで食い尽くす。特に、スライド数が多いファイルや画像が埋め込まれたファイルが混在すると、OSはスワップアウトを起こし、処理時間は指数関数的に増大する。

今回実装するアーキテクチャの肝は以下の3点だ。

1. WMIによるリアルタイム監視: `Win32_Processor` から負荷を取得し、閾値を超えたらスレッドを休止させる。
2. イベント駆動型の堅牢設計: 処理の合間に `DoEvents` を挟むのは定石だが、今回はそれを「負荷調整」のために活用する。
3. プロセス分離への布石: 失敗したファイルで全体の処理が止まらないよう、個別のファイル処理を独立させる設計思想。

—

2. 実装:CPU負荷連動型PDFバッチ・コントローラー

このコードは、CPU負荷が80%を超えた場合に処理を一時停止し、リソースが回復するまで待機する「自己制御型」のロジックである。

Option Explicit

‘ 物理CPU負荷を取得するためのWMIオブジェクト
Private objWMIService As Object

‘ CPU負荷率の閾値(%)
Private Const CPU_THRESHOLD As Integer = 80
‘ 監視間隔(ミリ秒)
Private Const SLEEP_INTERVAL As Long = 2000

”’

”’ 指定フォルダ内のPPTXを一括PDF変換(負荷制御付)
”’

Public Sub BatchConvertPPTXToPDF_Optimized(sourceFolder As String, outputFolder As String)
Dim fso As Object: Set fso = CreateObject(“Scripting.FileSystemObject”)
Dim folder As Object: Set folder = fso.GetFolder(sourceFolder)
Dim file As Object

Set objWMIService = GetObject(“winmgmts:\\.\root\cimv2”)

For Each file In folder.Files
If LCase(fso.GetExtensionName(file.Name)) = “pptx” Then

‘ 負荷監視・スロットリング
Call ThrottleProcess

‘ 変換処理実行
Call ConvertToPDF(file.Path, outputFolder & “\” & fso.GetBaseName(file.Name) & “.pdf”)

End If
Next file
End Sub

”’

”’ CPU負荷を監視し、過負荷時は待機する
”’

Private Sub ThrottleProcess()
Dim cpuLoad As Integer

Do
cpuLoad = GetCurrentCPULoad()
If cpuLoad < CPU_THRESHOLD Then Exit Do ' 負荷が高い場合はログを出し、待機 Debug.Print "CPU Overload detected: " & cpuLoad & "%. Sleeping..." Application.Wait (Now + TimeValue("0:00:03")) DoEvents Loop End Sub '''

”’ WMI経由でCPU負荷を取得
”’

Private Function GetCurrentCPULoad() As Integer
Dim objProcessor As Object
Dim colProcessors As Object

Set colProcessors = objWMIService.ExecQuery(“Select LoadPercentage from Win32_Processor”)
For Each objProcessor In colProcessors
GetCurrentCPULoad = objProcessor.LoadPercentage
Exit Function
Next
End Function

—

3. プロダクション環境での重要注意点

コードが動くことと、業務で使えることは別次元の話だ。以下の点に注意せよ。

  • WMIのコスト: `GetObject(“winmgmts:…”)` は軽量ではない。ループのたびにインスタンス化するのではなく、クラスレベルの変数として保持し、再利用せよ。上記のコードはそれを考慮した設計になっている。
  • 例外処理の徹底: 大量処理において「1つのファイルが壊れている」ことは日常茶飯事だ。`ConvertToPDF` 内には必ず `On Error Resume Next` を含め、失敗したファイル名をログファイル(CSV推奨)に出力するエラーハンドリングを実装すること。
  • メモリ解放: PowerPointのオブジェクトは、処理後に `Set obj = Nothing` を明示的に呼び出すこと。これを怠ると、VBAが終了してもプロセスがメモリ上に残り続け、次のバッチ処理でリソース枯渇を招く。

4. 次なるステップ:非同期化への挑戦

もし、あなたがこのコードをさらに高次元へ引き上げたいなら、次は「非同期処理」を検討すべきだ。VBA単体ではマルチスレッドは組めないが、VBScriptをシェル経由で呼び出し、並列プロセスを管理するコントローラーを作成することで、CPUコアを最大限活用しつつ、負荷が上がれば「子プロセスの数を減らす」という本格的なスケジューリングが可能になる。

自動化とは、単なる作業の代替ではない。リソースを支配し、予測可能性を担保するエンジニアリングそのものだ。この堅牢なアーキテクチャが、あなたの現場での安定稼働に寄与することを確信している。

タイトルとURLをコピーしました