Registration-Free のアクティブ化.NET-Based コンポーネント: チュートリアル

 

Steve White
開発者向けの Premier サポート(Microsoft UK)

Leslie Muller
グローバルITリサーチ & 開発、クレディスイスファーストボストン

2005 年 7 月

の概要: Microsoft Platform SDK は、分離されたアプリケーションとサイド バイ サイド アセンブリトピックを文書化する優れた作業を行います。 ただし、すべてのユーザーがこのトピックを COM コンポーネントの登録不要のアクティブ化と同一視しているわけではありません。 登録不要の COM は、ロックダウンされたサーバーとアプリケーションが共有インフラストラクチャ上に分離されている企業にとって非常に興味深いプラットフォーム機能です。 この記事では、COM 相互運用機能を介したネイティブ クライアントによる .NET Framework ベースのコンポーネントの登録不要なアクティブ化の作業例について説明します。 (11ページ印刷)

適用対象:
   Microsoft Windows Server 2003
   Microsoft Windows XP Service Pack 2
   Microsoft .NET Framework バージョン 1.1
   Microsoft Visual Studio .NET 2003
   Microsoft Visual Basic 6.0

この記事に付属するサンプルをダウンロードします。MSDNRegFreeNet.msi

コンテンツ

紹介
Registration-Free COM の用語
サンプルの実行
COM サーバーとしての .NET アセンブリのビルド
クライアントのビルド
Registration-Free アクティブ化
トラブルシューティング
結論
その他の資料

紹介

登録不要の COM は、Microsoft Windows XP (.NET Framework ベースのコンポーネント用 SP2) および Microsoft Windows Server 2003 プラットフォームで使用できるメカニズムです。 名前が示すように、このメカニズムを使用すると、COM コンポーネントを登録しなくても、コンピューターに COM コンポーネントを簡単に (XCOPY など) デプロイできます。

ターゲット プラットフォームでは、プロセスとその依存モジュールを初期化する段階の 1 つは、関連付けられている マニフェスト ファイルアクティブ化コンテキストと呼ばれるメモリ構造に読み込みます。 対応するレジストリ エントリがない場合は、COM ランタイムに必要なバインディングとアクティブ化の情報を提供するアクティブ化コンテキストです。 アクティブ化コンテキスト APIを使用してアクティブ化コンテキストを自分で作成してファイルの使用を無効にしない限り、COM サーバーまたはクライアントで特別なコードは必要ありません。

このチュートリアルでは、Visual C++ と Visual Basic 6.0 で記述されたネイティブ COM クライアントから、単純な .NET アセンブリを構築し、登録済みと登録解除の両方で使用します。 ソース コードとサンプルをダウンロードしてすぐに動作を確認することも、チュートリアルに従って自分でステップ バイ ステップでビルドすることもできます。

Registration-Free COM の用語

.NET テクノロジに精通しているユーザーは、アセンブリ という用語に慣れている、1 つのモジュールが 1 つのユニットとしてデプロイされ、名前が付けられ、バージョン管理され、1 つのモジュールにセットを定義する マニフェスト が含まれていることを意味します。 登録不要の COM では、アセンブリ と マニフェスト 用語は、概念的には似ていますが、対応する .NET と同じではないアイデアのために借用されます。

登録不要の COM では、アセンブリ を使用して、1 つ以上の PE モジュール (ネイティブ またはマネージド) のセットを 1 つのユニットとしてデプロイ、名前付け、バージョン管理することを意味します。 登録不要の COM では、マニフェスト を使用して、XML を含む .manifest 拡張子を持つテキスト ファイルを参照します。このファイルは、アセンブリ (アセンブリ マニフェスト) の ID とそのクラスのバインドとアクティブ化の詳細を定義するか、1 つ以上のアセンブリ ID 参照と共に アプリケーション (アプリケーション マニフェスト) の ID を定義します。 アセンブリ マニフェスト ファイルにはアセンブリの名前が付けられ、アプリケーション マニフェスト ファイルにはアプリケーションの名前が付けられます。

side-by-side (SxS) アセンブリ という用語は、マニフェスト ファイルを介して同じ COM コンポーネントの異なるバージョンの構成を指し、登録する必要なく、異なるスレッドによって同時に読み込むことができます。 SxS は、登録不要の COM有効にし、疎に同義です。

サンプルの実行

サンプル コードをダウンロードして抽出すると、\deployedというフォルダーが見つかります。 ここでは、Visual C++ バージョンのクライアント アプリケーション (client.exe)、そのマニフェスト (.manifestclient.exe)、および C# バージョンの COM サーバー (SideBySide.dll) を示します。 先に進み、client.exeを実行します。 予想される結果は、client.exeSideBySideClass (SideBySide.dllで実装) のインスタンスをアクティブ化し、"1.0.0-C#" のような Version メソッドを呼び出した結果を表示することです。

COM サーバーとしての .NET アセンブリのビルド

手順 1

Visual Studio .NET 2003 で、新しい C# を作成するか、Visual Basic .NET クラス ライブラリ プロジェクト を し、それを SideBySide呼び出します。 AssemblyInfo を削除します。[cs/vb] プロジェクトからファイルを し、次のようにクラスを実装します。

C# コード

using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: Guid("[LIBID_SideBySide]")]

namespace SideBySide
{
   [Guid("[IID_ISideBySideClass]")]
   public interface ISideBySideClass
   {
      string Version();
   }

   [Guid("[CLSID_SideBySideClass]")]
   public class SideBySideClass : ISideBySideClass
   {
      public string Version()
      {
         return "1.0.0-C#";
      }
   }
}

Visual Basic .NET コード

Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices

<Assembly: AssemblyVersion("1.0.0.0")> 
<Assembly: Guid("[LIBID_SideBySide]")>

<Guid("[IID_ISideBySideClass]")> _
Public Interface ISideBySideClass
    Function Version() As String
End Interface

<Guid("[CLSID_SideBySideClass]")> _
Public Class SideBySideClass
    Implements ISideBySideClass
    Function Version() As String Implements ISideBySideClass.Version
        Version = "1.0.0-VB.NET"
    End Function
End Class

プロジェクトに特有の GUID 値をプレースホルダーの形式で記述しました。 guidgen ツールを使用して一意の GUID を生成する必要があります。これは、後でプレースホルダーを使用するときに使用するそれぞれの値になります。

手順 2

ビルド時にタイプ ライブラリが生成されて登録されるように、プロジェクトの COM 相互運用機能の登録 設定を true に設定します。

手順 3

リリース ビルドを生成し、\deployedSideBySide.dll をコピーします。

クライアントのビルド

次の手順では、クライアントをビルドします。このチュートリアルでは、Visual C++ または visual Basic 6.0 クライアント をビルドするオプションがあります。

手順 4 (オプション A: Visual C++)

SideBySide プロジェクトのフォルダーを基準にして、クライアント と呼ばれる新しい Visual C++ Win32 コンソール プロジェクト を兄弟フォルダーに作成します。 Win32 アプリケーション ウィザードの [アプリケーション設定] タブで、[ATL のサポートを追加する] チェック ボックスをオンにします。

stdafx.h 編集し、の直後のファイルの先頭に次の行を追加します。

#define _WIN32_DCOM

また、stdafx.h ファイルの下部に次の行を追加します。

import "[path]\SideBySide.tlb" no_namespace

ここで、[path] は、SideBySide アセンブリをビルドしたときに生成されたタイプ ライブラリへの相対パスである必要があります。 通常、このパスは、手順 1 で C# または Visual Basic .NET プロジェクトのどちらを選択したかによって異なります。

client.cpp の内容を次のコードに置き換えます。

#include "stdafx.h"
#include <iostream>
using namespace std;

void ErrorDescription(HRESULT hr)
{
    TCHAR* szErrMsg;
    if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
      FORMAT_MESSAGE_FROM_SYSTEM, 
      NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
      (LPTSTR)&szErrMsg, 0, NULL) != 0)
   {
        cout << szErrMsg << endl;
        LocalFree(szErrMsg);
    }
   else
        cout << "Could not find a description for error 0x" 
           << hex << hr << dec << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
   CoInitializeEx(0, COINIT_MULTITHREADED);

   {
      ISideBySideClassPtr ptr;
      HRESULT hr = 
              ptr.CreateInstance(__uuidof(SideBySideClass));
      if (SUCCEEDED(hr))
      {
         cout << ptr->Version() << endl;
      }
      ErrorDescription(hr);

      char c;
      cin >> c;
   }

   CoUninitialize();

   return 0;
}

リリース ビルドを生成し、\deployed\release\client.exe をコピーします。

手順 4 (オプション B: Visual Basic 6.0)

Visual Basic 6.0 Standard EXE プロジェクト 新しいプロジェクトを作成します。 プロジェクト エクスプローラー で、Project1 ノードを選択し、[プロパティ ウィンドウ]でその名前 クライアントに変更します。 ファイル 選択 |プロジェクト名を 保存し、フォーム ファイルとプロジェクト ファイルを、SideBySide プロジェクトのフォルダーを基準にした兄弟フォルダーに保存します。 プロジェクト 選択 |参照し、SideBySide の横にあるチェックボックス オンにして、[OK]選択します。

フォーム デザイナーでメイン フォームをダブルクリックし、Sub Form_Load()内に次のコードを貼り付けます。

    Dim obj As New SideBySideClass
    Dim isxs As SideBySide.ISideBySideClass
    Set isxs = obj
    MsgBox isxs.Version()

ファイル 選択 |... client.exe し、\deployed フォルダーに移動し、[OK]選択します。

手順 5

現時点では、\deployed フォルダーには、中間ファイルとは別に、client.exeSideBySide.dllのみを含める必要があります。後者はビルド プロセスによって登録されます。 このような状況でサーバーとクライアントが連携していることを確認するには、\deployed\client.exe を実行し、予想される出力 "1.0.0-C#" または "1.0.0-VB.NET" に注意してください。

手順 6

このチュートリアルでは、登録不要 COM について説明しているため、SideBySide アセンブリの登録を解除する必要があります。 Visual Studio 2003 コマンド プロンプトで、\deployed フォルダーに移動し、次のコマンドを実行します: regasm /u SideBySide.dll

手順 7

前の手順で発生した影響を確認するには、\deployed\client.exe をもう一度実行すると、"クラスが登録されていません" または "実行時エラー '429': ActiveX コンポーネントはオブジェクトを作成できません" というメッセージが表示されます。 この段階では、COM ランタイムがレジストリで必要な情報を見つけることに不満を感じていましたが、代替手段で情報を利用できるようにはまだありません。 この問題は、次の手順で解決します。

Registration-Free アクティブ化

手順 8

\deployed フォルダーで、client.exe アプリケーションのアプリケーション マニフェスト ファイル (テキスト ファイル) を作成し、.manifestclient.exe呼び出します。 次のコードをファイルに貼り付けます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
   manifestVersion="1.0">
<assemblyIdentity
            type = "win32"
            name = "client"
            version = "1.0.0.0" />
<dependency>
            <dependentAssembly>
                        <assemblyIdentity
                                    type="win32"
                                    name="SideBySide"
                                    version="1.0.0.0" />
            </dependentAssembly>
</dependency>
</assembly>

手順 9

SideBySide プロジェクトのフォルダーで、プライベート アセンブリ マニフェスト ファイル (テキスト ファイル) を作成し、それを SideBySide.manifest呼び出します。 次のコードをファイルに貼り付けます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" 
  manifestVersion="1.0">
<assemblyIdentity
            type="win32"
            name=" SideBySide"
            version="1.0.0.0" />
<clrClass
            clsid="{[CLSID_SideBySideClass]}"
            progid="SideBySide.SideBySide"
            threadingModel="Both"
            name="SideBySide.SideBySideClass" >
</clrClass>
</assembly>

次のタスクでは、上記のアセンブリ マニフェスト ファイルを Win32 リソースとして SideBySide アセンブリに埋め込みます。 現時点では、これは Windows XP では必須ですが、Windows Server 2003 では必須ではありません。 Windows Server 2003 では、アセンブリ マニフェスト ファイルをアセンブリと共に配置するだけで、 できます。 ただし、今後の Windows Server 2003 Service Pack で変更される可能性があるため、この動作に依存しないことをお勧めします。 今後も両方のプラットフォームをサポートし続けるには、次のいくつかの手順に従い、アセンブリ マニフェスト ファイルを Win32 リソースとして .NET アセンブリに埋め込みます。 これは、の登録不要なアクティブ化にのみ必要です。NET ベースの コンポーネントであり、ネイティブ COM コンポーネント 登録不要のアクティブ化の要件ではありません。

手順 10

SideBySide プロジェクトのフォルダーで、リソース定義スクリプト ファイル (テキスト ファイル) を作成し、それを SideBySide.rc呼び出します。 次のコードをファイルに貼り付けます。

#include <windows.h>
#define MANIFEST_RESOURCE_ID 1
MANIFEST_RESOURCE_ID RT_MANIFEST SideBySide.manifest

windows.h ファイルとその依存関係は、Platform SDK (Core SDK セクション) または Visual C++ をインストールするときに使用できます。 ここで必要 windows.h の定義は次のとおりです。

#define RT_MANIFEST 24

その結果、SideBySide.rc の内容 解決されます。

1 24 SideBySide.manifest

ただし、指示どおりにマクロ定義を使用する方が、より明確で一般的です。

手順 11

SideBySide プロジェクトのフォルダーにビルド コマンド ファイル (テキスト ファイル) を作成し、それを build.cmd呼び出します。 次のコードをファイルに貼り付けます。

C# をビルドするには:

rc SideBySide.rc
csc /t:library /out:..\deployed\SideBySide.dll 
/win32res:SideBySide.res Class1.cs

Visual Basic .NET をビルドするには:

rc SideBySide.rc
vbc /t:library /out:..\deployed\SideBySide.dll 
/win32resource:SideBySide.res /rootnamespace:SideBySide Class1.vb

これらのコマンドは、まずプラットフォーム SDK (rc.exe) から Microsoft Windows リソース コンパイラ ツールを呼び出して、手順 10 のリソース定義スクリプトを、SideBySide.resという名前のコンパイル済みリソース ファイルにコンパイルすることです。次に、C# または Visual Basic .NET コンパイラを呼び出して、ソース コード ファイルをアセンブリにビルドし、コンパイルされたリソース ファイルを Win32 リソースとして埋め込みます。 コンパイルされたアセンブリは、\deployed フォルダーに書き込まれますが、COM 相互運用のために登録

手順 12

Visual Studio 2003 コマンド プロンプトで、SideBySide プロジェクトのフォルダーに移動し、次のコマンドを実行します: buildします。

手順 13

マニフェスト ファイルを使用して、クライアントが COM 相互運用機能を使用して SideBySideClass クラスをアクティブ化できるようになったことを確認するには、\deployed\client.exe を実行し、予想される出力 "1.0.0-C#" または "1.0.0-VB.NET" を書き留めます。

トラブルシューティング

これまでに説明したように、.NET Framework ベースのコンポーネントの登録不要なアクティブ化には、サーバーまたはクライアントで特別なコードは必要ありません。 必要なのは一致するマニフェスト ファイルのペアです。そのうちの 1 つは、RT_MANIFEST型の Win32 リソースとして .NET アセンブリに埋め込まれています。

このチュートリアルの方法で、独自の登録不要の開発にアプローチすることをお勧めします。 具体的には、まず、登録済みサーバーでクライアントが動作していることを確認して、既知の状態に到達します。サーバーの登録を解除し、エラー メッセージが想定どおりであることを確認します。マニフェスト ファイルを作成して配置することで、最後に状況を解決します。 これにより、登録不要のアクティブ化に関するトラブルシューティング作業は、マニフェスト ファイルの構造とアセンブリ マニフェストの正しい埋め込みに限定されます。

登録不要の COM の問題をトラブルシューティングする場合、Windows Server 2003 のイベント ビューアーはフレンドです。 Windows XP または Windows Server 2003 で構成エラーが検出されると、通常、起動したアプリケーションのタイトルのエラー メッセージ ボックスが表示され、「アプリケーションの構成が正しくないため、このアプリケーションを起動できませんでした。 アプリケーションを再インストールすると、この問題が解決する可能性があります。このメッセージが表示されるたびに、Windows Server 2003 で問題を再現し、システム イベント ログを参照し、SideBySide ソースからイベントを検索することをお勧めします。 私がこれらのケースでXPのイベントログを見るとは思わないのは、「[パス]\[アプリケーションファイル名]に失敗したアクティベーションコンテキストを生成する」などのメッセージが必ず含まれているということです。積荷目録。 参照エラー メッセージ: 操作は正常に完了しました。これは問題の特定には役立ちません。

マニフェスト ファイルの構造に進む前に、Win32 リソースについて説明しましょう。 前述のように、windows.h では、RT_MANIFESTシンボルが値 24 として定義されます。これは、オペレーティング システムが埋め込みマニフェスト ファイルとして認識する値です。 windows.h をリソース定義スクリプト (.rc ファイル) に含め忘れた場合でも、ビルドは成功し、マニフェスト ファイルはリソースとして埋め込まれますが、正しい型は埋め込まれません。 マニフェストが正しく埋め込まれたことを確認するには、Visual Studio (SideBySide.dllファイル |開く |File...).モジュール内のリソースを示すツリー ビューが表示されます。 ルート ノードの下には、マニフェスト リソースのリソース番号を示す別のノードRT_MANIFESTという名前のノードが必要です (チュートリアルでは 1)。 この最後のノードをダブルクリックしてバイナリ ビューにデータを表示し、XML マニフェスト ファイルに似ているかどうかを簡単にサニティ チェックします。 バイナリですが、ASCII 範囲の文字は明らかです。 バイナリ データが見つからないか、正しく見つからない場合は、リソース定義スクリプト (.rc ファイル) がマニフェスト ファイルを参照していることを確認します。 RT_MANIFEST ノードのテキストが引用符で囲まれている場合は、リソース定義スクリプト (.rc ファイル) に windows.h 含め忘れた可能性があります。

前述の各エラーは、Windows Server 2003 システム イベント ログで、「依存アセンブリ [名前] が見つからず、最後のエラーが参照されているアセンブリがシステムにインストールされていません」というメッセージと共に報告されます。

さまざまなマニフェスト ファイルのスキーマは、プラットフォーム SDK マニフェスト ファイルリファレンスという見出しの下に記載されています。また、Manifestchk.vbs スキーマ検証ツールを使用できるため、ここではチュートリアルに関連するいくつかの点のみを説明します。 まず、アセンブリ マニフェスト ファイルを調べてみましょう。 たとえば、手順 9 を振り返ります。

登録不要の COM 意味では、アセンブリ は、アセンブリ マニフェスト ファイルの内容を使用して 1 つ以上の物理ファイルを関連付ける抽象的な概念であることを思い出します。

assemblyIdentity 要素は、アセンブリの ID を定義します。 対して。NET ベースのコンポーネントの 属性は、.NET アセンブリの名前とファイル名と一致する必要があります。それ以外の場合は、Windows Server 2003 システム イベント ログに次のメッセージが表示されます。"依存アセンブリ [名の値 属性] が見つかりませんでした。最後のエラーは参照先アセンブリがシステムにインストールされていません。ただし、バージョン 属性は、.NET アセンブリの AssemblyVersionや、その AssemblyFileVersionと一致する必要はありませんが、何らかの一貫性を適用することをお勧めします。

clrClass 要素には、 と clsidという 2 つの必須属性しかありません。 属性 は、アクティブ化される CLR クラスの名前空間とクラス名の組み合わせに一致 必要があります。 そうでない場合、CoCreateInstance は値がCOR_E_TYPELOAD (0x80131522) の HRESULT を返します。 これは、.NET アセンブリで要求された CLR 型が型ローダーで見つからない場合に、System.TypeLoadException がスローされた結果です。 .NET アセンブリが Visual Basic .NET で記述されている場合に注意する必要があるのは、コマンド ラインで /rootnamespace スイッチを Visual Basic .NET コンパイラ (vbc.exe) に提供することです。 clsid 属性 は、GuidAttribute を介してアクティブ化される CLR クラスに割り当てられている CLSID と一致 必要があります。 そうでない場合、CoCreateInstance は値 REGDB_E_CLASSNOTREG (0x80040154) を持つ HRESULT を返します。メッセージ テキストは "Class not registered" です。

次に、アプリケーション マニフェスト ファイルに注目してみましょう。 たとえば、手順 8 を振り返ります。 アプリケーション マニフェスト [application filename].manifest形式で名前を付ける必要があります。 そのため、このチュートリアルでは.manifest client.exe名前を付け、client.exe がプロセスに読み込まれるたびに読み取る必要があることを明確にしました。 これが正しく行われなければ、CoCreateInstance は値 REGDB_E_CLASSNOTREG (0x80040154) を持つ HRESULT を返します。メッセージ テキストは "Class not registered" です。

アプリケーション マニフェストの最も重要な要素は、dependentAssembly/assemblyIdentity 要素です。 この要素はアセンブリ マニフェスト内の同等の要素への参照であり、2 つは正確に一致する必要があります。 これを確実に行う良い方法は、アセンブリ マニフェストから要素をコピーし、ここに貼り付けることです。 何らかの違いがある場合は、Windows Server 2003 システム イベント ログに"マニフェストで見つかったコンポーネント ID が、要求されたコンポーネントの ID と一致しません" というメッセージが表示されます。

結論

登録不要の COM は、WINDOWS レジストリへの依存関係から COM コンポーネントを解放し、その結果、専用サーバーを必要としないようにそれらを使用するアプリケーションを解放するテクノロジです。 これにより、同じ COM コンポーネントの異なるバージョンに依存するアプリケーションがインフラストラクチャを共有し、.NET のバージョン管理と配置メカニズムのエコーでそれらのさまざまな COM コンポーネントのバージョンを並べて読み込むことができます。

この記事では、Visual C++ と Visual Basic 6.0 の両方で記述されたネイティブ クライアント アプリケーションによる .NET Framework ベースのコンポーネントの登録不要なアクティブ化のデモについて説明しました。 このメカニズムのしくみの一部について説明し、考えられる構成エラーとそのトラブルシューティング方法を下線で示しました。

その他の資料

  • COM コンポーネントのアクティブ化の Registration-Free: チュートリアル
  • 分離アプリケーションとサイド バイ サイド アセンブリの
  • マニフェスト ファイル スキーマ の
  • アクティブ化コンテキスト API を使用した

 

作成者 について

Steve White は、Microsoft UK の Premier Support for Developers チームで働くアプリケーション開発コンサルタントです。 Visual C#、Windows フォーム、ASP.NET を使用した開発のお客様をサポートしています。 彼の ブログ は、音楽、視覚化、プログラミングに関する彼の興味についての詳細情報を持っています。

Leslie Muller は、Credit Suisse First Boston のリサーチ & 開発チームの技術者です。 Leslieは、金融サービス、テクノロジースタートアップ、産業オートメーション、防衛などの環境で働く開発者および技術アーキテクトとして12年の経験を持っています。 プログラミングや研究をしていないとき、彼はスキー、アイスホッケーを楽しみ、可能な場合はアイスランドやロッキーズのような極端な環境で電動車で少し狂った事をしています。