C#製のDLLをVBAから呼び出すのにいちいちRegAsmするのも面倒くさいなー、と思っていたところ、数年前のkumattiさんのツイートを思い出しました。
XL2013CPの件はこれで解決。
レジストリ未登録でのCOMコンポーネント利用
http://t.co/4neJuVk1
(DataObject は無理でしょうけど)
— kumatti (@kumatti1) 2012, 12月 12
そういえばMicrosoft.Windows.ActCtxオブジェクトを使えばレジストリ登録不要でCOMコンポーネント呼び出せたなー、と。
- Microsoft.Windows.ActCtxでWSHでもReg‐Free COM
- http://dev.activebasic.com/egtra/2012/07/07/498/
- .NETでのRegFree-COM
- http://dev.activebasic.com/egtra/2014/10/06/685/
やったことないし、一回くらいはやってみるか!
・・・というわけで、さっそく試してみることにしました。
ソースコードの準備
まずは呼び出す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でもリソースのコンパイルができるようなので、これを使うことにします。
- 「64-bit programming using the “Go” tools」から「Gorc.zip」ファイルをダウンロードして、「C:\System\Gorc」フォルダに解凍します。
- 上記手順で作成したマニフェストファイル(SampleNameSpace.manifest)をGoRC.exeと同じフォルダ(C:\System\Gorc)にコピーします。
- テキストエディタで下記ファイルを作成します。
- 下記コマンドを実行し、リソース(res)ファイルを作成します。
- 作成したSampleNameSpace.resファイルを「C:\System」フォルダにコピーします。
C:\System\Gorc\SampleNameSpace.rc
#include <windows.h> #define MANIFEST_RESOURCE_ID 1 MANIFEST_RESOURCE_ID RT_MANIFEST SampleNameSpace.manifest
C:\System\Gorc>GoRC /r "SampleNameSpace.rc"
ソースコードのコンパイル
リソースファイルの準備ができたら、次はコンパイル(/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ページ
- Registration-Free Activation of .NET-Based Components: A Walkthrough
- https://msdn.microsoft.com/ja-jp/library/ms973915.aspx
- 方法: 登録を必要としないアクティベーション用の .NET Framework ベースの COM コンポーネントを構成する
- https://msdn.microsoft.com/ja-jp/library/eew13bza.aspx
- Microsoft.Windows.ActCtxでWSHでもReg‐Free COM
- http://dev.activebasic.com/egtra/2012/07/07/498/
- .NETでのRegFree-COM
- http://dev.activebasic.com/egtra/2014/10/06/685/
- Genman32 – A tool to generate Sxs manifest for managed assembly for Registration Free COM/.Net Interop
- http://blogs.msdn.com/b/junfeng/archive/2007/04/14/genman32-a-tool-to-generate-sxs-manifest-for-managed-assembly-for-registration-free-com-net-interop.aspx
- Side-by-side Assembly Development Tools
- https://msdn.microsoft.com/ja-jp/library/aa376592.aspx
- Registration-Free COM components try-out
- http://jwbs-blog.blogspot.jp/2009/06/registration-free-com-components.html
- Registration-free COM components try-out (continued)
- http://jwbs-blog.blogspot.jp/2009/06/registration-free-com-components_16.html
- Regfree COM einer .NET-COM-dll mittels Activation Context API unter VB6/VBA
- https://social.msdn.microsoft.com/Forums/de-DE/b25144d7-f99a-4951-b16e-b1e1d1194207/regfree-com-einer-netcomdll-mittels-activation-context-api-unter-vb6vba?forum=dotnetframeworkde
- Cannot get registration-free COM working from VBA
- http://stackoverflow.com/questions/15503117/cannot-get-registration-free-com-working-from-vba
- RegFree COM working from C#, NOT working from VBA
- http://stackoverflow.com/questions/9805228/regfree-com-working-from-c-not-working-from-vba
- COM Side by Side Assemblies using dll’s from another directory?
- http://stackoverflow.com/questions/9004299/com-side-by-side-assemblies-using-dlls-from-another-directory
- COM-Schnittstellen-Elemente
- http://source.access-codelib.net/listing.php?repname=CodeLib&path=%2Fbranches%2Fdraft%2Fcom%2F#path_branches_draft_com_
この記事へのコメントはありません。