vs2013 のatlプロジェクトで、regfree com を作るメモ。
(主にマニュフェストツール(mt.exe)を利用する話なので、特にvsバージョンは関係ないはず。。)
regfree なcomの手順
その1. COMプロジェクトおよびatlシンプルオブジェクトを作る。
普通のdllサーバーを作る。外部COMサーバーは無理。
その2. 1つのcoclassに1つsxs用マニュフェストファイルを生成しておく。
例えば、ビルド後イベントにrgsファイル毎に mt.exe でsxs用マニュフェストファイルを生成するコマンドラインを追加しておく。
例: PkyPresenterActivate というcoclassを作った。tlbはcomのdllに含まれている。
rgs ファイル名:PkyPresenterActivate.rgs
出力する manifest ファイル名: PkyPresenterActivate.sxs.manifest
mt -nologo -tlb:"$(TargetPath)" -dll:"$(TargetFileName)" -rgs:"PkyPresenterActivate.rgs" -out:"$(OutDir)PkyPresenterActivate.sxs.manifest"
これを、coclass毎に追加しておく。
普通は作り直すことは無いだろうから、初回ビルド後一度手動で生成しておくの方が楽そう。
rgsファイルは、CLSIDとか‘ThreadingModel等が記述されているものを間違えずに指定する。lib用のrgsファイル(何も書いてない)と間違えない。
その3. その後、利用側で複数のmanifestファイルを追加する。
プロジェクトのプロパティより、[マニュフェストツール]→[入出力]→[追加のマニュフェストファイル]に先ほど生成したファイルを追加。
「;」で複数ファイルを区切るらしい。
複数のmanifestファイルを追加するとき、重複した comInterfaceExternalProxyStub タグが気になるけど、
出力されたexe中の manifest ファイルを確認すると同じIIDはのっていない。(重複登録はされていないらしい)
(別の方法)1つのcoclassだけ利用するとき
その1. COMプロジェクトおよびatlシンプルオブジェクトを作る。
tlb ファイルと該当COCLASSのrgs ファイルを取っておく。
非ATLなら、coclass の rgs ファイルを作成する。
その2. 読み込む側のEXEのプロジェクトプロパティを開く
- 「マニュフェストツール」→「分離されたCOM」を開く
- 「タイプライブラリファイル」と「レジスタスクリプトファイル」に COMモジュール作成時にとっておいたファイルを設定する。
- コンポーネントファイル名に 作成したCOM DLL名を書く。
その後、普通のCOM利用時と同様に、xxx_i.h/xxx_i.c ファイル(midlの出力ファイル)を追加する。COMを利用するコードを書けば regsvr32 しなくてもCOMが利用できる。
自分の勘違い:RegFreeCOM という名前から、COM側に設定するものだと思っていたけれど、Client側の設定だった。COM自体には別に何もしなくていい。(tlbを取り込んでおくなどは必要。とりあえず、atlプロジェクトのデフォルト状態で十分。)
何が起きているのかのメモ
マニュフェストツールのコマンドラインを確認すると、
/dll:"PkyCustomPresenter.dll" /verbose /rgs:"PkyPresenter.rgs" /out:"Debug\TestRegfree1.exe.embed.manifest" 以下略
マニュフェストファイル生成コードが追加されている。
出力先が、組み込みマニュフェストファイルへ直接出力するように設定されている。
生成された組み込まれるマニュフェストファイル
$(IntDIR)TestRegfree1.exe.embed.manifest を覗いてみると確かに comclass の設定が記述されている。
バラバラに追加
1. tlb ファイルだけ→ coclass の threadingmodel / progid の記述が無い。
2. rgs ファイルだけ→ typelib / comInterfaceExternalProxyStub の記述が無い。
両方設定する必要がありそう。
[分離COM] の設定では1つのcoclassしかダメらしい。
rgs ファイルに複数記述すると、正しく複数の設定を読み込めないらしい。
http://stackoverflow.com/questions/13572218/registration-free-com-threading-models-mt-exe-and-rgs-scripts
( ゚Д゚).。o○(分離されたCOMって、結局何を分離しているんだろぅ・・?
csharp のプロジェクトに、それを組み込む時の追記
処理部分はc++,comで、GUIはwpfにするとき、上の方法を取ろうとしても、visual studio 上(csharpのプロパティ)でmanifestを追加するUIが見あたらない。
(正しくは、1つのminifest fileしか登録できないらしい。)
とりあえず、手動でRegFreeComの記述を追記したメモ。
- app.manifest を追加する。 csharp の新しい項目の追加から、アプリケーションマニフェストファイルを追加。 既に作ってあるなら、以下の作業はそれに追加する。
- 上記manifestファイルの「</assembly>」の前に、以下を追加。 (assemblyの子要素ならどこに挿入してもいいはず。)
<file name="Pinky.Presenter.dll" hashalg="SHA1">
<comClass clsid="{put-YOUR_GUID_HERE-bbbb-bbbbbbbb}" tlbid="{put-YOUR_GUID_HERE-aaaa-aaaaaaa}" threadingModel="Both" progid="Pinky.Presenter.Activate">
<progid>Pinky.Presenter.Activate.1</progid>
</comClass>
<comClass clsid="{put-YOUR_GUID_HERE-cccc-cccca}" tlbid="{put-YOUR_GUID_HERE-aaaa-aaaaaaa}"></comClass>
<typelib tlbid="{put-YOUR_GUID_HERE-aaaa-aaaaaaa}" resourceid="1" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib>
</file>
これは、上記の "PkyPresenterActivate.sxs.manifest" の出力内容から、「assemblyの子要素」を切り出したもの。
- これで、csharp がメインの実行ファイルでも、reg free com が利用できる。
TODO: 手動コピーの記事を昔見かけたのでそれのリンクを追加。
-rgs: オプションを複数書けば、1つのファイルにたくさん書ける。
複数マニュフェストをマージする方法
mt -manifest "マニュフェストファイルその1.manifest" "マニュフェストファイルその2.manifest" -out:"出力ファイル"
- 各COCLASS、個別にregfree用のマニュフェストファイルを生成する。
- 上記コマンドでマージして1つのマニュフェストファイルへまとめる。=> これを利用してハッピー。