« スパイダーマン3 | トップページ | 黄金週間も終わりです »

2007年5月 5日

VSIでシリアル番号検証

VSIでシリアル番号を入力する必要があったので、いろいろ調べてみると標準の機能だと、検証するのは数値のみで、しかもそれらを加算して7で割れた場合には正しいというものでした。
これじゃ、すべての値に0を入れてしまえば、素通りになってしまいます。
あまり使える機能じゃありません。
インターネットでいろいろ調べるとマイクロソフト社の公式情報がありました。しかし、この情報はVSI1.0/1.1向けで、Visual Studio 2005のVSI2.0向けじゃないみたいです。しかも、微妙に分かりにくい。
ただ、これでも問題ないのですが…
さらにインターネットを探すとVSI2.0向け(というかVisual Studio 2005向け)の情報が、Validating a Product Key in a VS.NET Installにあり、それを参考にしました。

<とりあえず必要な物>
- Visual Studio 2005 Professional Edition以上
- Platform SDK(のWindows Installer SDK)

<シリアル検証用DLL>
シリアル番号を検証するためのDLLを作成します。
特別なDLLという訳ではなく、普通のDLLとして作成すれば動作します。
→サンプル(VerifyPID.ZIP)

#include "stdafx.h"
#include <Msiquery.h>

#pragma comment(lib, "msi.lib")

BOOL APIENTRY DllMain(HMODULE hModule,
                   DWORD ul_reason_for_call,
                   LPVOID lpReserved
)
{
    return TRUE;
}

extern "C" UINT __stdcall VerifyPID(MSIHANDLE hInstall)
{
  UINT nRetVal = 0;
  TCHAR szPidKey[MAX_PATH] = {0};
  int str = -1;

  DWORD dwBuffer = sizeof(szPidKey)/sizeof(TCHAR);

  // 入力されたプロダクトIDを取り出す
  UINT uiMsiRc = MsiGetProperty(hInstall, TEXT("PIDKEY"), szPidKey, &dwBuffer);

  if (ERROR_SUCCESS == uiMsiRc)
  {
    // プロダクトIDを比較
    // * VSIでテンプレートを"<???-######>"とした場合
    str = lstrcmp(szPidKey, TEXT("ABC-123456"));
  }

  // "PIDCHECK"プロパティは、ORCAで追加するプロパティ
  if (str == 0)
  {
    // "PIDCHECK"プロパティを"TRUE"に設定する
    MsiSetProperty(hInstall, TEXT("PIDCHECK"), TEXT("TRUE"));
  }
  else
  {
    // "PIDCHECK"プロパティを"FALSE"に設定する
    MsiSetProperty(hInstall, TEXT("PIDCHECK"), TEXT("FALSE"));
    // 自分でメッセージを出さないと、VSIでは正しくない場合には警告が表示されない
    MessageBox(NULL, TEXT("入力されたキーは正しくありません"), TEXT("セットアップ"), MB_OK | MB_ICONEXCLAMATION);
  }

  return 0;
}

<MSIの変更>
MSIファイルを変更する必要があります。
これは、MSIファイルを作成する度に修正する必要があります。
この毎回の作業が面倒臭いし、自動化できないのが問題です。
MSIの変更は、Platform SDK(Install SDK)に含まれるorcaというツールで行います。ただし、このツールは、別途自分でインストールしないといけません。

(1) シリアル検証用DLLの埋め込み
テーブルの"Binary"に新規に"Row"を追加します。
  Name   VerifyDLL  (ここは好きな名前で問題ない)
 
Data   作成したシリアル検証用DLL
この作業によりシリアル検証用DLLがMSIに組み込まれるようです。

(2)  カスタムアクションを定義する
テーブルの"CustomAction"に以下の項目を追加する
  Action    CheckPID  (ここは好きな名前で問題ない)
  Type       1
  Source   VerifyDLL  (DLLの埋め込みの"Name"で指定した名前)
  Target   VerifyPID (DLLの関数名)
Targetで指定するのは、DLLの関数名なのですが、DEFファイルで定義している場合には、その名前にします。
DEFファイルを用いないでdllexportで指定している場合には、"_VerifyPID@4"のように指定します。面倒なのでDEFファイルを指定したほうが間違いありません。

(3) プロパティ追加
プロパティを追加します。このプロパティは、DLL内でも利用しますので、あまり名前を変更しないほうが良いでしょう。
テーブルの"Property"に追加します。
  Property   PIDCHECK
  Value         FALSE

(4) 判定を行う
判定を行うダイアログのイベントを変更します。
テーブルの"ControlEvent"を変更(今までのように追加じゃありません)します。
フィールド"Dialog"が"CustomerInfoForm"が対象となります。
  (a) コントロールが"NextButton"、イベントが"ValidateProductID"の項目
     イベント"ValidateProductID"を"DoAction"に変更
     アーギュメント"{}"を"CheckPID"(カスタムアクションのAction)に変更
  (b) コントロールが"NextButton"、イベントが"NewDialog"の項目
    コンディションを
      (PIDCHECK="TRUE") AND CustomerInfoForm_NextArgs<>"" AND CustomerInfoForm_ShowSerial<>""
    に変更

(5) 変更したMSIを保存する
今までの変更を修正して保存します。

おしまい

自動化するのは難しいのですが、orcaのImport機能を使うことで、比較的間違いなく変更することができます。

例えば、以下のファイルを"Property.idt"として保存し、ocraからImportすると、簡単にプロパティを追加することができます。
この場合には、Import時に"marge"を指定してください。

Property Value
s72 l0
932 Property Property
PIDCHECK FALSE

フォーマットが分かれば、orcaでExportして編集しておくことで、簡単にmargeすることができます。
Exportしたファイルを変更する場合には、先頭の3行は変更してはいけません。変更するのは4行目からです。
ただし、今回はCustomActionだけは変更なので、margeできませんので気をつけてください。
無理にImportする場合には、margeでmargeした後に、不要となる行を削除します。

|

« スパイダーマン3 | トップページ | 黄金週間も終わりです »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/2700/14961392

この記事へのトラックバック一覧です: VSIでシリアル番号検証:

« スパイダーマン3 | トップページ | 黄金週間も終わりです »