.NETアセンブリによるCOMサーバーでもマニフェストによるRegFree-COMが可能なことを知ったので、試してみました。さらに、CLR 4(.NET Framework 4~4.5)、CLR 2(.NET Framework 2.0~3.5)の両方で動くようにする方法を調べました。
まずはCOMサーバー側、C#です。
// t.cs using System; using System.Reflection; using System.Runtime.InteropServices; [assembly:AssemblyVersion("1.0.0.0")] namespace MyLibrary { [Guid("1144264c-b871-496b-b771-0448f48ffbab")] public class Hoge { [DispId(0)] public string Test() { return Environment.Version.ToString(); } } } |
上をcsc /t:libraryでコンパイルし、t.dllを作ります。このとき、.NET Framework 2.0/3.0/3.5ターゲットでビルドします。
そして、これに対するアセンブリマニフェストt.manifestを用意します。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <assemblyIdentity name="t" type="win32" version="1.0.0.0"/> <clrClass clsid="{1144264C-B871-496B-B771-0448F48FFBAB}" threadingModel="Both" name="MyLibrary.Hoge" runtimeVersion="v4.0.30319;v2.0.50727"/> <file name="t.dll"/> </assembly> |
runtimeVersion=”v4.0.30319;v2.0.50727″は、CLR 4.0があればそれを、なければ2.0を使う指定です。1つだけを書けばそれだけを使うことになります。1つだけ指定するほうが一般的でしょう。
次に、使う側です。
#include <iostream> #include <windows.h> #include <atlcomcli.h> #pragma comment(linker, "/manifestdependency:\"type='win32' name='t' version='1.0.0.0' language='*'\"") class __declspec(uuid("1144264c-b871-496b-b771-0448f48ffbab")) Hoge; int main() { ATLENSURE_RETURN_VAL(SUCCEEDED(CoInitialize(nullptr)), 1); ATL::CComPtr<IDispatch> u; auto hr = CoCreateInstance(__uuidof(Hoge), nullptr, CLSCTX_ALL, IID_PPV_ARGS(&u)); std::cout << std::hex << hr << std::endl; ATL::CComVariant result; hr = u.Invoke0(static_cast<DISPID>(0), &result); std::cout << std::hex << hr << std::endl; result.ChangeType(VT_BSTR); std::wcout << result.bstrVal << std::endl; } |
ここでは、インタフェース定義の手間を省くためIDispatchを使いましたが、その他のインタフェースでももちろん上手くいくことと思います。
manfiestファイルの記述については、方法: 登録を必要としないアクティベーション用の .NET Framework ベースのコンポーネントを構成するで見つけました。また、runtimeVersionの指定については、In-Proc SxS and Migration Quick Start – .NET Blogでこのセミコロン区切りで複数指定できることを見つけました。
スポンサード リンク |
[…] http://dev.activebasic.com/egtra/2014/10/06/685/ […]