他の Office ソリューションから VSTO アドインのコードを呼び出す

VSTO アドイン内のオブジェクトは、他の Microsoft Office ソリューションを含む、他のソリューションに公開できます。 このことは、VSTO アドインが他のソリューションで使用可能なサービスを含む場合に便利です。 たとえば、Web サービスから受け取る財務データについて計算を実行する、Microsoft Office Excel 向けの VSTO アドインがある場合、他のソリューションでは、実行時に Excel VSTO アドインを呼び出すことでこれらの計算を実行できます。

適用対象: このトピックの情報は、VSTO アドイン プロジェクトに適用されます。 詳細については、「Office アプリケーションおよびプロジェクトの種類別の使用可能な機能」を参照してください。

この処理には主に 2 つの手順があります。

  • VSTO アドインで、オブジェクトを他のソリューションに公開します。

  • もう 1 つのソリューションで、VSTO アドインにより公開されたオブジェクトにアクセスし、オブジェクトのメンバーを呼び出します。

アドイン内のコードを呼び出すことができるソリューションの種類

VSTO アドイン内のオブジェクトは次の種類のソリューションに公開できます。

  • VSTO アドインと同じアプリケーション プロセスに読み込まれるドキュメント内の Visual Basic for Applications (VBA) コード。

  • VSTO アドインと同じアプリケーション プロセスに読み込まれるドキュメント レベルのカスタマイズ。

  • Visual Studio に含まれる Office プロジェクト テンプレートを使用して作成された他の VSTO アドイン。

  • COM VSTO アドイン (つまり、 IDTExtensibility2 インターフェイスを直接実装する VSTO アドイン)。

  • VSTO アドインとは異なるプロセスで実行中の任意のソリューション (こうした種類のソリューションは アウト プロセス クライアントとも呼ばれます)。 これらには、Windows フォームまたはコンソール アプリケーションなど、Office アプリケーションを自動化するアプリケーションと、異なるプロセスに読み込まれる VSTO アドインが含まれます。

他のソリューションにオブジェクトを公開する

VSTO アドイン内のオブジェクトを他のソリューションに公開するには、VSTO アドインで次の手順を実行します。

  1. 他のソリューションに公開するクラスを定義します。

  2. RequestComAddInAutomationService クラスの ThisAddIn メソッドをオーバーライドします。 他のソリューションに公開するクラスのインスタンスを返します。

他のソリューションに公開するクラスを定義する

少なくとも、公開するクラスはパブリックであり、 ComVisibleAttribute 属性の設定は trueであり、 IDispatch インターフェイスを公開する必要があります。

IDispatch インターフェイスを公開する推奨方法は以下の手順を実行することです。

  1. 他のソリューションに公開するメンバーを宣言するインターフェイスを定義します。 このインターフェイスは、VSTO アドイン プロジェクトで定義できます。 ただし、クラスを非 VBA ソリューションに公開する場合、このインターフェイスを別のクラス ライブラリ プロジェクトで定義することを推奨します。そうすることで、VSTO アドインを呼び出すソリューションは VSTO アドイン プロジェクトを参照することなく、インターフェイスを参照できます。

  2. ComVisibleAttribute 属性をこのインターフェイスに適用し、この属性を true に設定します。

  3. クラスを変更して、このインターフェイスを実装します。

  4. ClassInterfaceAttribute 属性をクラスに適用し、この属性を ClassInterfaceType 列挙体の None 値に設定します。

  5. このクラスをアウト プロセス クライアントに公開する場合、次も実行する必要がある可能性があります。

    • StandardOleMarshalObjectからクラスを派生させます。 詳細については、「アウト プロセス クライアントにクラスを公開する」を参照してください。

    • インターフェイスを定義するプロジェクトで、 [COM の相互運用機能に登録] プロパティを設定します。 このプロパティは、クライアントで事前バインディングを使用して VSTO アドインを呼び出せるようにする場合にのみ必要です。

    次のコード例は、他のソリューションによって呼び出し可能な AddInUtilities メソッドを持つ、 ImportData クラスを示します。 より大きなチュートリアルのコンテキストでこのコードを確認するには、「チュートリアル: VSTO アドイン内のコードを VBA から呼び出す」を参照してください。

    [ComVisible(true)]
    public interface IAddInUtilities
    {
        void ImportData();
    }
    
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class AddInUtilities : IAddInUtilities
    {
        // This method tries to write a string to cell A1 in the active worksheet.
        public void ImportData()
        {
            Excel.Worksheet activeWorksheet = Globals.ThisAddIn.Application.ActiveSheet as Excel.Worksheet;
    
            if (activeWorksheet != null)
            {
                Excel.Range range1 = activeWorksheet.get_Range("A1", System.Type.Missing);
                range1.Value2 = "This is my data";
            }
        }
    }
    

VBA にクラスを公開する

上記の手順を実行すると、VBA コードはインターフェイス内で宣言するメソッドのみを呼び出すことができます。 VBA コードは、 Objectなど、クラスが基本クラスから取得するメソッドを含め、クラス内の他のメソッドを呼び出すことはできません。

代わりに、ClassInterfaceAttribute 属性を ClassInterfaceType 列挙体の AutoDispatch または AutoDual 値に設定し、IDispatch インターフェイスを公開できます。 インターフェイスを公開する場合、メソッドを別のインターフェイスで宣言する必要はありません。 ただし、VBA コードは、 Objectなど、基本クラスから取得されるメソッドを含め、クラス内の任意のパブリックおよび非静的メソッドを呼び出すことができます。 さらに、事前バインディングを使用するアウト プロセス クライアントはクラスを呼び出すことができません。

アウトプロセス クライアントにクラスを公開する

VSTO アドイン内のクラスをアウト プロセス クライアントに公開する場合、 StandardOleMarshalObject からクラスを派生させ、アウト プロセス クライアントが公開された VSTO アドイン オブジェクトを呼び出せるようにする必要があります。 そうしないと、アウト プロセス クライアントで公開されたオブジェクトのインスタンスを取得しようとしたとき、予期せずに失敗する可能性があります。

この失敗は、Office アプリケーションのオブジェクト モデルのすべての呼び出しはメイン UI スレッド上で実行される必要があるのに対して、アウト プロセス クライアントからオブジェクトへの呼び出しは任意の RPC (リモート プロシージャ コール) スレッドに到着するために発生します。 .NET Framework における COM マーシャリング機構はスレッドを切り替えず、メイン UI スレッドではなく、受信 RPC スレッド上のオブジェクトに呼び出しをマーシャリングすることを試みます。 オブジェクトが StandardOleMarshalObjectから派生するクラスのインスタンスである場合、オブジェクトへの受信呼び出しは、公開されたオブジェクトが作成されたスレッド、つまりホスト アプリケーションのメイン UI スレッドに自動的にマーシャリングされます。

Office ソリューションにおけるスレッドの使用法の詳細については、「Office でのスレッドのサポート」を参照してください。

RequestComAddInAutomationService メソッドをオーバーライドする

次のコード例は、VSTO アドイン内の RequestComAddInAutomationService クラスで ThisAddIn をオーバーライドする方法を示します。 この例では、他のソリューションに公開する AddInUtilities という名前のクラスを定義済みであると想定しています。 より大きなチュートリアルのコンテキストでこのコードを確認するには、「チュートリアル: VSTO アドイン内のコードを VBA から呼び出す」を参照してください。

private AddInUtilities utilities;

protected override object RequestComAddInAutomationService()
{
    if (utilities == null)
        utilities = new AddInUtilities();

    return utilities;
}

VSTO アドインが読み込まれると、Visual Studio Tools for Office ランタイムで RequestComAddInAutomationService メソッドが呼び出されます。 ランタイムでは、返されるオブジェクトを、VSTO アドインを表す COMAddIn オブジェクトの COMAddIn.Object プロパティに割り当てます。 この COMAddIn オブジェクトは他の Office ソリューションおよび Office を自動化するソリューションで利用できます。

他のソリューションからオブジェクトにアクセスする

VSTO アドインで公開されたオブジェクトを呼び出すには、クライアント ソリューションで以下の手順を実行します。

  1. 公開された VSTO アドインを表す COMAddIn オブジェクトを取得します。 クライアントは、ホスト Office アプリケーションのオブジェクト モデル内の Application.COMAddIns プロパティを使用して、使用可能なすべての VSTO アドインにアクセスできます。

  2. COMAddIn オブジェクトの COMAddIn.Object プロパティにアクセスします。 このプロパティは VSTO アドインから公開されたオブジェクトを返します。

  3. 公開されたオブジェクトのメンバーを呼び出します。

    COMAddIn.Object プロパティの戻り値を使用する方法は VBA クライアントと非 VBA クライアントで異なります。 アウト プロセス クライアントの場合、可能性のある競合状態を避けるために追加のコードが必要です。

VBA ソリューションからオブジェクトにアクセスする

次のコード例は、VBA を使用して、VSTO アドインにより公開されたメソッドを呼び出す方法を示しています。 この VBA マクロでは、ExcelImportData という名前の VSTO アドインで定義される ImportData という名前のメソッドを呼び出します。 より大きなチュートリアルのコンテキストでこのコードを確認するには、「チュートリアル: VSTO アドイン内のコードを VBA から呼び出す」を参照してください。

Sub CallVSTOMethod()
    Dim addIn As COMAddIn
    Dim automationObject As Object
    Set addIn = Application.COMAddIns("ExcelImportData")
    Set automationObject = addIn.Object
    automationObject.ImportData
End Sub

非 VBA ソリューションからオブジェクトにアクセスする

非 VBA ソリューションでは、実装されるインターフェイスに COMAddIn.Object プロパティ値をキャストする必要があり、その後、インターフェイス オブジェクト上で公開されたメソッドを呼び出すことができます。 次のコード例は、Visual Studio に含まれる Office Developer Tools を使用して作成された異なる VSTO アドインから ImportData メソッドを呼び出す方法を示します。

object addInName = "ExcelImportData";
Office.COMAddIn addIn = Globals.ThisAddIn.Application.COMAddIns.Item(ref addInName);
ExcelImportData.IAddInUtilities utilities = (ExcelImportData.IAddInUtilities)addIn.Object;
utilities.ImportData();

この例で、COMAddIn.Object プロパティの値を IAddInUtilities インターフェイスではなく AddInUtilities クラスにキャストしようとすると、コードによって InvalidCastException がスローされます。