yamamoWorks

.NET技術を中心に気まぐれに更新していきます

Interop.xxx.dll を配布したくない

一般的に.NETからCOMを使う場合、VS.NETの参照設定でCOMへの参照を追加しますが、その時に
Interop.xxx.dll というラッパーができます。このラッパーを通じて.NETからCOMへアクセスが行われます。

Windows Form アプリケーションの場合は特に気にすることは無いのですが、はてなブックマークMenuBar
のようにIEにホストされるようなアプリケーションの場合、Interop.xxx.dll をGACに登録する必要があったりします。

他の.NETアプリケーションでも同じCOMを使っていると同じ名前の Interop.xxx.dll
ができるわけで、それがGACに登録されてたりするとなんか影響しそうでいやな感じです。(実際には署名とかバージョンとかで大丈夫な仕組みになってるのかな?)


そこで、Interop.xxx.dll を配布しなくて済む方法を考えたのですが、方法は2つあるようです。


1.Type.GetTypeFromCLSID() を利用して InvokeMember
で操作する。

Type typ = Type.GetTypeFromCLSID(new System.Guid("{3050F4E7-98B5-11CF-BB82-00AA00BDCE0B}"));
object doc = ie.Document;
docTitle = typ.InvokeMember("title", BindingFlags.GetProperty, null, doc, null).ToString();
MessageBox.Show("Title is " + docTitle);

参考:MS ⇒ MSHTML のプライマリ interop アセンブリは、再頒布可能なファイルのサイズを増やします。

※ Type.GetTypeFromProgID("mhtmlfile") でもOK



2.必要なインターフェイスを自分で定義する

Interop.xxx.dll
はインターフェース定義がされた.NETアセンブリなわけで、同じコードを自分で書いてしまえということです。
例えば
WebBrowserClass なんかはこんな感じです。
[ComImport, Guid("8856F961-340A-11D0-A96B-00C04FD705A2")]
[ComSourceInterfaces("SHDocVw.DWebBrowserEvents2\0SHDocVw.DWebBrowserEvents\0")]
[TypeLibType((short) 0x22), ClassInterface((short) 0)]
public class WebBrowserClass : IWebBrowser
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(100)]
public virtual extern void GoBack();

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0x65)]
public virtual extern void GoForward();

[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0x66)]
public virtual extern void GoHome();

[DispId(200)]
public virtual extern object Application
{
[return: MarshalAs(UnmanagedType.IDispatch)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(200)]
get;
}

[DispId(0xc9)]
public virtual extern object Parent
{
[return: MarshalAs(UnmanagedType.IDispatch)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0xc9)]
get;
}

[DispId(0xcb)]
public virtual extern object Document
{
[return: MarshalAs(UnmanagedType.IDispatch)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime), DispId(0xcb)]
get;
}
  :
  :

必要となるコードは Interrop.xxx.dll を Reflector 等で覗いてやればすぐにわかります。
この方法は定義する必要があるクラスが多いと大変ですが (^^;