【入門編】【上級者向け】COMアドイン開発:プロジェクトのオープン・保存イベントを監視する常駐ツール – Project VBA解析バイブル

スポンサーリンク

こんにちは!プロジェクト管理の現場で、日々スケジュールやリソースの調整に奔走お疲れ様です。

「マクロの記録」から一歩踏み出し、VBAを使って日常の業務を自動化できるようになったあなたなら、きっとこんな壁にぶぶつかったことがあるはずです。

  • 「メンバーが勝手にプロジェクトファイルを保存してしまうのを防ぎたい」
  • 「全社共通のルールで、ファイルを開いた瞬間に特定のチェック走らせたい」
  • 「個別のファイルにマクロを埋め込むのではなく、すべてのProjectファイルで一括してイベントを監視したい」

通常のVBAマクロは、あくまで「開いているプロジェクトファイルの中」でしか動きません。そのため、新しいファイルを作られたり、マクロが入っていないファイルを勝手に操作されたりすると、途端に無力になってしまいます。

そこで今回は、一歩進んだ上級者向けのアプローチとして、「COMアドイン」を使ったプロジェクトのグローバル監視アーキテクチャを解説します。

「COMアドインって難しそう…」と思うかもしれませんが、ここをクリアすれば、あなたのProject VBAのスキルは間違いなくプロの領域に到達します。優しく紐解いていくので、一緒にマスターしていきましょう!

1. なぜ「COMアドイン」が必要なのか?

通常、私たちが書くVBAコードは、`ThisProject` モジュールなどに記述しますよね。これは「そのプロジェクトファイルが開かれている間だけ有効」というライフサイクルを持っています。

しかし、組織全体のプロジェクト管理を統制(ガバナンスを効かせる)するためには、以下のような要件が出てきます。

1. ユーザーがどんな名前のプロジェクトファイルを開いても、自動的に監視を始めたい。
2. 保存(`BeforeSave`)やオープン(`Open`)のタイミングで、勝手にコードを書き換えられないようにしたい。
3. すべてのPCに、同じロジックを強制的に適用したい。

これを実現するのが COMアドイン(Component Object Model Add-in) です。
VB.NET(C#でも可)を使って「外側」からMicrosoft Projectのアプリケーション全体(`MSProject.Application`)を監視し、イベントをフック(横取り)する仕組みを作ります。

2. 全体像:COMアドインのアーキテクチャ

まずは、どのような構造で動くのかイメージ図を見てみましょう。

[ Microsoft Project アプリケーション ]

├── ユーザーがファイルを開く / 保存する

▼ (イベント発生)
[ COMアドイン (VB.NET製 DLL) ] ← 常に裏側で常駐

├── グローバルイベントの検知 (ProjectOpen / BeforeSave)


[ 統制ロジックの実行 ]
・WBSの命名規則チェック
・ベースライン設定の強制
・不正な保存のキャンセル

COMアドインは、Visual Studio(VB.NETやC#)を使い、クラスライブラリとして作成します。これをWindowsのレジストリに登録することで、Project起動時に自動的に読み込まれ、裏側で常駐する仕組みです。

3. 実装ステップ:VB.NETによるCOMアドインの骨組み

それでは、実際に動くコードの骨組みを見ていきましょう。
今回はVisual Studioを使い、VB.NETで「Projectのオープンと保存を監視する常駐ツール」を作成する手順を解説します。

ステップ①:プロジェクトの作成と参照設定

1. Visual Studioを開き、「クラス ライブラリ (.NET Framework)」プロジェクトを新規作成します(※.NET Framework 4.8などが安定しておすすめです)。
2. 参照設定に以下を追加します。

  • `Microsoft.Office.Interop.MSProject` (COMタブから追加)
  • `Extensibility` (COMアドインのインターフェース用)

ステップ②:アドイン本体のコード実装

以下のコードは、COMアドインとして動作し、Projectのアプリケーションイベントをフックするメインクラスのサンプルです。

Imports Extensibility
Imports Microsoft.Office.Core
Imports MSProject = Microsoft.Office.Interop.MSProject


Public Class Connect
Implements IDTExtensibility2

‘ Project アプリケーションオブジェクトを保持
Private WithEvents projApp As MSProject.Application

‘ アドインが読み込まれた時に呼ばれる (イニシャライゼーション)
Public Sub OnConnection(application As Object, connectMode As ext_ConnectMode, addInInst As Object, ByRef custom As Array) Implements IDTExtensibility2.OnConnection
‘ Projectのアプリケーションインスタンスをキャプチャ
projApp = CType(application, MSProject.Application)
System.Windows.Forms.MessageBox.Show(“Project監視アドインが有効化されました。”, “Project Governance”)
End Sub

‘ アドインがアンロードされる時
Public Sub OnDisconnection(disconnectMode As ext_DisconnectMode, ByRef custom As Array) Implements IDTExtensibility2.OnDisconnection
projApp = Nothing
End Sub

‘ — 以下、その他のIDTExtensibility2必須メソッド(中身は空でOK) —
Public Sub OnAddInsUpdate(ByRef custom As Array) Implements IDTExtensibility2.OnAddInsUpdate End Sub
Public Sub OnStartupComplete(ByRef custom As Array) Implements IDTExtensibility2.OnStartupComplete End Sub
Public Sub OnBeginShutdown(ByRef custom As Array) Implements IDTExtensibility2.OnBeginShutdown End Sub

‘ =================================================================
‘ ここからが本番:グローバルイベントの監視
‘ =================================================================

‘ 1. プロジェクトオープン時のイベント
Private Sub projApp_ProjectOpen(ByVal pj As MSProject.Project) Handles projApp.ProjectOpen
‘ 組織の統制チェック:例として、オープン時にベースラインが未設定なら警告する
Try
If pj.Name <> “” Then
‘ ここにプロジェクトが開かれた瞬間に走らせたいロジックを書く
‘ 例: 必須カスタムフィールドのチェックなど
System.Diagnostics.Debug.WriteLine(“オープン検知: ” & pj.Name)
End If
Catch ex.Exception
System.Windows.Forms.MessageBox.Show(“エラーが発生しました: ” & ex.Message)
End Try
End Sub

‘ 2. プロジェクト保存前のイベント(保存のキャンセルも可能!)
Private Sub projApp.BeforeSaveProject(ByVal pj As MSProject.Project, ByRef Cancel As Boolean) Handles projApp.BeforeSaveProject
‘ 例:プロジェクト名に特定のルール(例: [PJ]など)が含まれていない場合、保存を拒否する
If Not pj.Name.StartsWith(“[PJ]”) Then
System.Windows.Forms.MessageBox.Show(
“【保存エラー】” & vbCrLf & “プロジェクト名の先頭には必ず ‘[PJ]’ を付与してください。”,
“組織統制ポリシー”,
System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Error
)

‘ 保存を強制キャンセル!
Cancel = True
End If
End Sub

End Class

4. 陥りやすいエラーとアーキテクチャの罠

このレベルの開発を行うと、VBA単体では遭遇しない独特のトラップにハマることがあります。エンジニアとして知っておくべき重要ポイントを挙げておきます。

罠①:COMの参照解放(メモリリーク)

VB.NETからProjectのオブジェクト(`Project` や `Task` など)を操作する際、背後ではCOMコンポーネントが動いています。
ループ処理などで `System.Runtime.InteropServices.Marshal.ReleaseComObject()` を適切に呼ばないと、Projectを閉じた後もプロセスが裏に残り続け(ゾンビプロセス)、次回起動時にファイルがロックされる原因になります。

罠②:イベント内での無限ループ

`BeforeSaveProject` の中でファイル名をプログラムから書き換えようとすると、「保存」→「イベント発火」→「ファイル名変更」→「再保存」の無限ループに陥り、Projectがフリーズします。
イベントハンドラ内では「データの読み取りや検証(Cancelの切り替え)」にとどめ、書き込みを行う場合は慎重にフラグ制御を行いましょう。

5. まとめ:ここをクリアすれば、Project VBAの基本はバッチリ!

今回は、あえて少し背伸びをした「COMアドインによるグローバル監視アーキテクチャ」をご紹介しました。

  • VBAマクロは、個別のファイル内を自動化する「特効薬」。
  • COMアドインは、組織全体をシステム的に守る「インフラ」。

この2つを使い分けられるようになれば、あなたはもはや「マクロが書ける一般社員」ではなく、立派な業務自動化・アーキテクチャ設計エンジニアです。

現場のルールを強制し、品質の担保されたプロジェクト管理を実現するために、ぜひこのアプローチに挑戦してみてください。あなたのエンジニアとしての引き出しが、確実に何段階もレベルアップしますよ!

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