Office関連

VBAからRegistration-Freeで.NETベースのDLLを呼び出す方法

C#製のDLLをVBAから呼び出すのにいちいちRegAsmするのも面倒くさいなー、と思っていたところ、数年前のkumattiさんのツイートを思い出しました。

そういえばMicrosoft.Windows.ActCtxオブジェクトを使えばレジストリ登録不要でCOMコンポーネント呼び出せたなー、と。

やったことないし、一回くらいはやってみるか!
・・・というわけで、さっそく試してみることにしました。

ソースコードの準備

まずは呼び出すDLLのコードをC#で書きます。

C:\System\SampleNameSpace.cs

using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly:AssemblyVersion("1.0.0.0")]

namespace SampleNameSpace
{
  [ComVisible(true), Guid("3ea27b1a-ac62-492e-8659-fd20402a629f"), InterfaceType(ComInterfaceType.InterfaceIsDual)]
  public interface ISample {
    string Hoge(string str);
  }
  
  [ClassInterface(ClassInterfaceType.None), Guid("14c829c3-4c16-4cb8-b1f1-7bec0528d009"), ProgId("Sample.ProgId")]
  public class SampleClass : ISample
  {
    public string Hoge(string str)
    {
      return "hogehoge:" + str;
    }
  }
}

文字列を返すだけの単純なコードです。

マニフェストファイルの作成

ソースコードの準備ができたら、次は「方法: 登録を必要としないアクティベーション用の .NET Framework ベースの COM コンポーネントを構成する」を参考に、DLLに埋め込むマニフェストファイルを作成します。

SampleNameSpace.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity name="SampleNameSpace" 
                    version="1.0.0.0" 
                    processorArchitecture="MSIL" />
  <clrClass clsid="{14C829C3-4C16-4CB8-B1F1-7BEC0528D009}" 
            progid="Sample.ProgId" 
            threadingModel="Both" 
            name="SampleNameSpace.SampleClass" 
            runtimeVersion="v4.0.30319;v2.0.50727" />
  <file name="SampleNameSpace.dll" />
</assembly>

上記参考ページを見る限り「/win32manifest」オプションでマニフェストを埋め込んでも良さそうな感じがしますが、手順として“コンポーネント マニフェストはリソースとしてアセンブリに埋め込む必要があります”とあるので、記載されている手順に従うことにします。

リソースファイルの作成

参考ページにはRc.exeを使用する旨が書いてあるのですが、「Win32ソースを実行ファイルに埋め込む: .NET Tips: C#, VB.NET」によるとGoRC.exeでもリソースのコンパイルができるようなので、これを使うことにします。

  1. 64-bit programming using the “Go” tools」から「Gorc.zip」ファイルをダウンロードして、「C:\System\Gorc」フォルダに解凍します。
  2. 上記手順で作成したマニフェストファイル(SampleNameSpace.manifest)をGoRC.exeと同じフォルダ(C:\System\Gorc)にコピーします。
  3. テキストエディタで下記ファイルを作成します。
  4. C:\System\Gorc\SampleNameSpace.rc

    #include <windows.h>
    #define MANIFEST_RESOURCE_ID 1
    MANIFEST_RESOURCE_ID RT_MANIFEST SampleNameSpace.manifest
  5. 下記コマンドを実行し、リソース(res)ファイルを作成します。
  6. C:\System\Gorc>GoRC /r "SampleNameSpace.rc"
  7. 作成したSampleNameSpace.resファイルを「C:\System」フォルダにコピーします。

ソースコードのコンパイル

リソースファイルの準備ができたら、次はコンパイル(/win32resオプションでリソースファイル指定)してDLLを作成します。

問題が無ければ「C:\System」フォルダに「SampleNameSpace.dll」ファイルが作成されます。

VBAからの呼び出し

VBAから呼び出す前に、呼び出し元(クライアント側)のマニフェストファイルを準備します。

C:\System\SampleNameSpace.client.manifest

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity name = "client" version = "1.0.0.0" />
  <dependency>
    <dependentAssembly>
      <assemblyIdentity name="SampleNameSpace" version="1.0.0.0" processorArchitecture="MSIL" />
    </dependentAssembly>
  </dependency>
</assembly>

マニフェストファイルの準備ができたら、いよいよVBAからの呼び出しです。

Public Sub Sample()
  Dim obj As Object
  
  With CreateObject("Microsoft.Windows.ActCtx")
    .Manifest = "C:\System\SampleNameSpace.client.manifest"
    Set obj = .CreateObject("Sample.ProgId")
    MsgBox obj.Hoge("ABC")
  End With
End Sub

ProgIdを指定してMicrosoft.Windows.ActCtx.CreateObjectメソッドを呼び出して、上手くいけばHogeメソッドの結果がメッセージボックスで表示されるはずです。

・・・が、返ってきたのは「実行時エラー ‘-2147024894 (80070002)’:オートメーション エラーです。指定されたファイルが見つかりません。」エラー。

Cannot get registration-free COM working from VBA」や「RegFree COM working from C#, NOT working from VBA」を見ると、“DLLをVBAの実行元(ExcelならEXCEL.EXE)と同じフォルダに置いたら動いた”とのことだったので、DLLファイルをOfficeのインストールフォルダにコピーして再実行したところ、無事にコードが実行できました。

しかしながら、RegAsmしたくないからMicrosoft.Windows.ActCtxオブジェクトを使ったというのに、結局Officeフォルダへのコピーが必要とは・・・。
これなら素直にRegAsmした方がマシなような気がします。

もしかしたら、コピー不要でDLLを呼び出す方法があるのかもしれませんが、そこまで調べきれていないので、何か進展があったらまた追記することにします。

中途半端なオチですが、参考にしたWebサイトとともにメモとして残しておきます。

参考Webページ

コメント

  • コメント (0)

  • トラックバックは利用できません。

  1. この記事へのコメントはありません。

Time limit is exhausted. Please reload CAPTCHA.

最近の記事

アーカイブ

RapidSSL_SEAL-90x50
PAGE TOP