2012年1月18日水曜日

Reg-Free COM on .NET 2.0の実践

.NET 2.0 C#から、MFCで作ったようなCOM DLLを、レジストリに登録しないで呼び出す方法を、備忘したいと思います。
MFCにはCOleDataSourceクラスとか、OLEと連携する上で役立つクラスが多数有ります。

これらを.NETだけで実現しようとすると、膨大な手数になります。

C#でドラッグ・アンド・ドロップできるアプリ(バックアップの復元ソフト)を作る際に、活用できました。

具体的な手法は又の機会に譲るとして、ここでは要素技術のみを列挙いたします:

Handling Shell Data Transfer Scenarios
  FILEDESCRIPTOR
  FILECONTENTS
IAsyncOperation

Registration-Free Activation of COM Components: A Walkthrough
  Assembly Manifests

手順:

マニフェストファイルを用意します。紫色の部分を変えていきます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
      type="win32"
      name="DiffBkRestore"
      processorArchitecture="x86"
      version="1.0.0.0"
      />
  <file name="VFCopy.dll">
    <comClass clsid="{8FADBC22-CF67-4AEE-9B67-451C106B187E}" threadingModel="Apartment" />
  </file>
</assembly>


mt.exeでexeの中に入れ込みます。外付けのmanifestファイルでは、Reg-Freeが機能しませんでした。
紫色の部分を変えます。

mt.exe -manifest DiffBkRestore.manifest -outputresource:bin\x86\release\DiffBkRestore.exe;#1

私はNSISでセットアップを構築しています。NSISのビルド実行時にmt.exeが動くように作りこみするのも絶妙な手でしょう。

!system '"C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\Bin\mt.exe" -manifest DiffBkRestore.manifest -outputresource:bin\x86\release\DiffBkRestore.exe;#1' = 0
;C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\mt.exe
;C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\Tools\Bin\mt.exe
;C:\Program Files (x86)\Microsoft Visual Studio 8\SDK\v2.0\Bin\mt.exe

mt.exeのパスが大量にメモってあるのは、環境が変わった際に探しやすいようにする為です。

where mt.exeで探してきました。

NSISでは、!systemでシェルコマンドを実行できます。失敗したらビルドが停止するように、" = 0"を最後に足しています。指定しないと失敗しても止まりません→ほぼ確実に見落します。

後、注意点として、processorArchitecturex86等に固定しないといけません。

.NETのアセンブリは、x86でビルドしましょう。

Any CPUでビルドしてしまうと、64ビットWindowsでは、x64で起動してしまいます。これではx86で作ったCOM DLLを読み込みできません。具体的には、BadImageFormatExceptionが発生すると思います。