VBAまたはVBSからCOM経由で使用できる.NETのライブラリの作成方法

Table of Content

このドキュメントではVBAやVBScriptからCOM経由で.NETの処理を実行する方法について記述する。

環境

・Visual Studio2008 Pro
・.NET Framework 2.0 を対象とする。
・32ビットのOffice2010

.NETを使用したクラスモジュールをCOMにする方法

1.Visual Studio 2008 を管理者権限で起動する。
 これはCOM登録時にレジストリを変更するため。

2.プロジェクトの追加で「.NET Framework 2.0」 と 「クラスライブラリ」を選択
5sban21z.png

3. ビルドにてプラットフォームのターゲットを「x86」または「x64」とする。
これは使用するExcelに合わせる。

1w04banj.png

4. ビルドにてCOM相互運用機能の登録にチェックをつける。
1w04banj.png

5. アプリケーションのアセンブリ情報で、「アセンブリをCOM参照可能にする」
1w04banj.png

6. 公開したいインターフェイスとその実態について以下のように記述する

using System.Runtime.InteropServices;
namespace NMeCabCom
{
    [ComVisible(true)]
    public interface INmcTagger
    {
        void Create();
        NmcNode[] Parse(string text);
    }

    [ClassInterface(ClassInterfaceType.None)]
    public class NmcTagger : INmcTagger
    {
        private MeCabTagger nmcab;
        public NmcTagger()
        {
        }

        public void Create()
        {
            MeCabParam p = new MeCabParam();
            p.DicDir = @"C:\dev\NMeCab\dic\ipadic";

            this.nmcab = MeCabTagger.Create(p);
        }

        public NmcNode[] Parse(string text)
        {
            List<NmcNode> result = new List<NmcNode>();
            if (this.nmcab == null)
            {
                return result.ToArray();
            }
            MeCabNode node = this.nmcab.ParseToNode(text);
            while (node != null)
            {
                result.Add(new NmcNode(node));
                node = node.Next;
            }
            return result.ToArray();
        }

    }
}

まず、公開するインターフェイスの直前に「ComVisible(true)」と記述する。

    [ComVisible(true)]
    public interface INmcTagger
    {
        void Create();
        NmcNode[] Parse(string text);
    }

そして、そのインターフェイスの実装部分はClassInterfaceType.Noneとする。

    [ClassInterface(ClassInterfaceType.None)]
    public class NmcTagger : INmcTagger

7. ビルドを行うことでCOMの登録まで行われる

インターフェイスの設計時に注意すべきこと。

・List<>などのジェネリック型はCOMとしては公開できない

・ClassInterfaceTypeにAutoDualを記述すると、インターフェイス不要にできるがすべきでない
http://msdn.microsoft.com/ja-jp/library/ms182205.aspx

・Uint、ULONG等のUnsignedの型をインターフェイスに使用してはいけない
COMとしては使用できても、VBAやVBSはUnsignedをサポートしていないので、ULONGなどのインターフェイスは使用できない。

・オブジェクトの配列は返えしてはいけない

以下のようなCOMのインターフェイスがあったとする。

    public interface INmcTagger
    {
        string GetModulePath();
        void Create(NmcParam p);
        NmcNode[] Parse(string text);
    }

このインターフェイスの場合、VBAやC#などの型を明示できるプログラミング言語では適切に処理できる

Dim ret As NmcNode()
ret = t.Parse("This is a pen.")

しかし、VBSの場合、型が明示できないため、Unknownとなり処理できなくなる。

Dim ret ' As NmcNode()
ret = t.Parse("This is a pen.")
WScript.Echo TypeName(ret) ' Unknownとなり、以降処理できない。

こういう場合は、配列を管理するインターフェイスを作成して、それを経由するようにする。

    public interface INmcNodeCollection
    {
        int Count { get; }
        NmcNode GetItem(int index);
    }

配列ではないオブジェクトを返した場合は、VBSでも処理ができる

set ret = t.Parse("This is a pen.")
For i = 0 To ret.Count- 1
  WScript.Echo TypeName(ret.GetItem(i))
  WScript.Echo ret.GetItem(i).Surface
Next

利用方法

開発環境以外の登録方法

.NET Frameworkのフォルダに存在するregasmを使用する。
作成したdllに対して /tlb と /codebase を付与してregasmを実行する。
regasmは各バージョンの.NETに存在する。

SET BIN=C:\Windows\Microsoft.NET\Framework\v2.0.50727

REM 登録
%BIN%\regasm  C:\dev\NMeCabCom\NMeCabCom\bin\Debug\NMeCabCom.dll /tlb /codebase

この際、以下のメッセージが出力される場合がある。

「RegAsm : warning RA0000 : 署名されていないアセンブリを /codebase を使用して登録すると、同じコンピュータにインストールされるその他のアプリケーションとの競合が生じる可能性があります。/codebase スイッチは署名されたアセンブリのみに使用できます。アセンブリに厳密な名前を付けて、再登録してください。」

これは、警告だけであり、COMの登録はされている。
この警告を消すには、プロジェクトの設定で「署名」→「アセンブリの署名」 厳密な名前のキーファイルを選択する必要がある。

1w04banj.png

依存するすべてのDLLが同様に厳密な名前を有しなければならないので気をつけること。

COMの削除方法

/tlb と /unregister を付与したregasmコマンドを実行後、ファイルを消すればよい。

regasm /tlb C:\dev\NMeCabCom\NMeCabCom\bin\Debug\NMeCabCom.dll  /unregister

ExcelVBAで利用する方法

参照設定してやれば、使用できるようになる
1w04banj.png

以下のようにインテリセンスが効く。
1w04banj.png

VBSからの利用方法

以下のようにCreateObjectを利用する。

set t = CreateObject("NMeCabCom.NmcTagger")

実際のサンプル

VBAやVBScriptで形態素解析を行う方法
http://qiita.com/mima_ita/items/bc2aeb060ee12d280d7b

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です