作成日: 2008/11/01

ATL でライセンスコントロールを作成し Web に埋め込む

概要

ATL でライセンスコントロールを作成して Web に埋め込んでみました。
ライセンスコントロールでは実行時にライセンスキーの有無をチェックしてコントロールの生成を制御できます。

以下のサンプルプロジェクトは、Windows Vista SP1 + Visual Studio 2008 で作成しました。

ライセンスコントロールを作成する

Visual Studio を起動し、メニューから [ファイル] - [新規作成] - [プロジェクト] で [新しいプロジェクト] を開きます。
[プロジェクトの種類] で「Visual C++」を選び、[テンプレート] に「ATL プロジェクト」を指定します。 [プロジェクト名] は「MyTest」としました。
入力できたら [OK] をクリックします。

新しいプロジェクト

[ATL プロジェクトウィザード] が開きます。[次へ] をクリックします。

ATL プロジェクトウィザード1

[アプリケーションの設定] はデフォルトのまま、[完了] をクリックします。

ATL プロジェクトウィザード2

作成したプロジェクトに ATL コントロールを追加します。
[ソリューションエクスプローラ] でプロジェクト「MyTest」を右クリックし、[追加] - [クラス] を選びます。

クラスの追加

[クラスの追加] が開きます。[カテゴリ] に [ATL]、[テンプレート] に [ATL コントロール] を選び、[追加] をクリックします。

クラスの追加画面

[ATL コントロールウィザード] が開きます。[C++] の [短い名前] は「MyTestCtrl」としました。
また、[短い名前] 以外の部分は自動的に補足入力されたものをそのまま使いました。
入力できたら [次へ] をクリックします。

ATL コントロールウィザード1

[オプション] で [ライセンス] にチェックを入れ、[完了] をクリックします。

ATL コントロールウィザード2
ライセンスコントロールのためのクラスを修正する

ライセンスコントロールのためのコードは ATL の CComClassFactory2 にあります。
ATL コントロールの作成時に ATL コントロールウィザードのオプションでライセンスをチェックすると、ウィザードにより 'C + コントロール名 + Lic' という名前でクラスが定義され、定義されたクラスを引数とした DECLARE_CLASSFACTORY2 マクロを利用する 1 文が、作成するコントロールのクラスに追加されて、CComClassFactory2 の実装が取り込まれます。
また、IDL にも licensed の 1 行が追加されます。
IDL の licensed は MSDN によれば、「適用対象のコクラスがライセンスされており、IClassFactory2 を使用してインスタンスを生成する必要があることを示します。」 とのことです。
なお、ATL の CComClassFactory2 は IClassFactory2 を実装しています。

ウィザードにより作成された CMyTestCtrlLic クラスには 3 つの関数メンバが定義されています。

ウィザードにより生成されたクラス

それぞれの関数は次の役割を持ちます。

  • IsLicenseValid()

    ライセンスキー無しでコントロールが作成されるときに呼び出されます。
    関数の戻り値として TRUE を返却するとコントロールのインスタンスが生成され、FALSE を返却すると生成されません。

  • VerifyLicenseKey()

    ライセンスキー付きでコントロールが作成されるときにライセンスキー文字列を引数として呼び出されますので、
    ライセンスキー文字列が正しいかをチェックします。 関数の戻り値として TRUE を返却するとコントロールのインスタンスが生成され、FALSE を返却すると生成されません。

  • GetLicenseKey()

    ライセンスキー文字列を返却します。
    コントロールのライセンスキー文字列を取得するために、ツールやコンテナなどから呼び出されます。
    後述する lpk_tool (ライセンスキー文字列をファイルに保存するツール) の実行時にもこの関数が呼び出され、 ライセンスキー文字列を取得しています。

ちなみに、上記のコードのままビルドした場合、IsLicenseValid() が無条件に TRUE を返しているため、 ライセンスキー無しでもコントロールのインスタンスを作成できてしまうため、ライセンスコントロールとしての意味を持ちません。

IsLicenseValid() で無条件に FALSE を返しても良いのですが、そうすると、コントロールの開発時もライセンスキー文字列を扱わなければならず、 開発が面倒くさくなりそうです。
また、GetLicenseKey() では念のため IsLicenseValid() の結果を確認してから文字列を返すようにしたほうが良さそうです。

とりあえず、ここでは以下の方針を取りました。

  • 開発時には開発環境に C:\MyTest.BuildEnv というファイルを作成しておくことにする。 IsLicenseValid() では、このファイルが存在すれば TRUE を返すようにする。

  • GetLicenseKey() では IsLicenseValid() が TRUE の場合のみライセンス文字列を返すようにする。

ということで以下のように変更しました。
なお、製品としてライセンスコントロールを作成する場合、このような単純な実装は避けた方がよさそうです。念のため。。。

変更後のクラス
ビルドしてコントロールを登録する

プロジェクト MyTest を Release ビルドします。
※ATL コントロールウィザード実行時に一緒に作成されている MyTestPS はビルドしなくて構いません。

ただし、Visual Studio で開発している場合、プロジェクトの設定をウィザードで作成したときのままビルドしてしまうと、 いくつかの dll に依存するコントロールができてしまいます。
このプロジェクトの場合、Release ビルドすると ATL90.dll (ATL ランタイム)、 MSVCR90.dll (C ランタイム)に依存するコントロールが作成されます。このままでは コントロールを実行する Windows にこれらの dll が存在しないと、コントロールが動作しません。
通常は CAB にまとめる際に、依存する dll を同梱して配布したりするのですが、CAB にするのが面倒くさかったので、 ここでは 静的ライブラリを使うようにプロジェクトを変更しました。

[ATL の使用] を [ATL に静的にリンク] に変更

ATL の使用

[ランタイム ライブラリ] を [マルチスレッド (/MT)] に変更

ランタイム ライブラリ

ちなみに、Vista の場合、Visual Studio を管理者権限で起動せずにビルドした場合、ビルドの最後に

error PRJ0050: 出力を登録できませんでした。ユーザーごとのリダイレクトを有効にするか、引き上げられたアクセス許可を使用して、コマンド プロンプトからコンポーネントを登録してください。

のようなエラーが出てコントロールを登録できません。 このため、コマンドプロンプトを管理者権限で開き、regsvr32 を使ってコントロールを登録する処理を、手作業で行う必要があります。

ライセンスキー文字列をファイル(LPK ファイル)に保存する

ライセンスコントロールを Web に埋め込む場合、ライセンスキー文字列をファイル(LPK ファイル)にしてライセンスマネージャに渡すことで、 ライセンスキー付きでコントロールのインスタンスが生成されるようになります。

[ActiveX] ライセンス付きActiveXコントロールをIEで使用する方法

また、LPK ファイルを作成するにはマイクロソフトが配布している lpk_tool を利用します。

License Package Authoring Tool

これをダウンロード、展開して利用します。

なお、LPK ファイルを作成する対象のコントロールは、レジストリに登録されており、 かつ、IsLicenseValid() が TRUE を返す状態でなければなりません。
レジストリの登録は、ビルドが成功し、かつ regsvr32 でのコントロールの登録が成功していれば大丈夫です。
また、このサンプルの実装では C:\MyTest.BuildEnv というファイルが存在すれば、IsLicenseValid() が TRUE を返すようにしてありますので、 C:\ に MyTest.BuildEnv というファイルを作成してください。
※ちなみに Vista の場合、C:\ にファイルを作成する際に、管理者権限が必要になる場合があります。

lpk_tool を起動します。
※なお、Vista の場合、lpk_tool を管理者権限で起動しておかないと LPK ファイル保存時にエラーになり保存できませんので、ご注意ください。

lpk_toolの実行1

[Available controls] で対象のコントロールを選択し、[Add] をクリックして、[Controls in license package] に移動します。
ここでは MyTestCtrl を選択しています。
※もし、複数の種類のライセンスコントロールを Web に埋め込む場合は、ここで複数選択します。

lpk_toolの実行2

[Save & Exit] をクリックして保存先ファイル名を指定し、[保存] をクリックして LPK ファイルを作成します。
ここでは「MyTestCtrl.lpk」というファイル名で保存しました。

lpk_toolの実行3
作成したコントロールを Web に埋め込む

作成したコントロールを Web で利用するためには、コントロールを object タグを使って埋め込むとともに、 ライセンスマネージャ (IE と一緒にインストールされているらしい) も object タグで埋め込み、 LPK ファイルをライセンスマネージャのパラメータとして指定します。
下図では「classid="clsid:5220cb21-c88d-11cf-b347-00aa00a28331"」の箇所がライセンスマネージャです。 param で LPKPath に作成した LPK ファイル 「MyTestCtrl.lpk」を指定しています。
また、「classid="clsid:a5fa28f4-78cc-4254-875d-dd3025fffef1"」の箇所が今回作成したコントロールです。
ご自分でプロジェクトを新規作成して試される場合は、この classid と codebase を作成するコントロールにあわせて変更してください。

コントロールを埋め込んだ Web のソース

ご参考までに、、、。
コントロールの classid はプロジェクトの IDL ファイルの library の uuid 部分から取得できます。
なお、Visual Studio でウィザードを使ってコントロールを作成した場合、 コントロールと同名の HTML ファイルがプロジェクトのディレクトリに作成され、 コントロールを埋め込んだソースが記述されていますので、それがそのまま使えます。

IDL ファイル

IDL ファイル

ウィザードで作成された HTML ファイル

ウィザードで作成された HTML ファイル

以下は実行結果です。なお、Web サーバは Vista 上で実行しましたが、ブラウズは Virtual PC 上の Windows XP SP3 上の IE 6 から行いました。
ちなみに、最近の IE はセキュリティの関係で、署名無しの Active X コントロールを実行するのが難しくなっています。 サンプルのコントロールを実行する際には、Web サイトを信頼済みにするだけで(色々と警告は出つつも)実行できましたが、 お使いの IE の設定や環境によっては、ほかにも色々と設定が必要な場合がありますので、ご注意ください。

また、Web サーバは IIS を動作させるのが面倒くさかったので、代わりに、手元にたまたまインストールしてあった Tomcat を使いました。 サンプルソースに web.xml が入っているのはそのためです。無精ですみません。。。

ウィザードで作成された HTML ファイル
サンプルソース

上の作業で使ったソリューションファイル一式と Web 用のファイルです。

サンプルソース (SampleProject.zip) (82.3 KB)