Programming Field - プログラミング Tips

ATL のレジストリ リソース

Visual C++ に付いてくる ATL (Active Template Library) は COM アプリケーションの開発に関してはかなり便利なライブラリです。この中に、「レジストリ リソース」というものがあります。このリソースは、独自のレジストリ ファイル「レジストリ スクリプト」のデータで、プログラム側からは CAtlModule::UpdateRegistryFromResourceSCAtlModule::UpdateRegistryFromResourceDCComModule::UpdateRegistryFromResourceSCComModule::UpdateRegistryFromResourceD のいずれかを呼び出して簡単にレジストリを登録することが出来ます。

ATL のウィザードを使って作成したプログラムには、_AtlModule または _Module という名前の変数が用意されています。これは、ATL がアプリケーションと COM との間に「仲立ち」するようなもので (間違っているかな?)、この変数は CAtlModule または CComModule から派生した、アプリケーション内で定義しているクラスのグローバル変数です。上記で紹介したメソッドを使うには、この変数を利用します。

まず、レジストリ スクリプトを作成します。概観は以下のとおりです。また、その下には(分かりにくい)説明があるので参考にしてください。。

<root-key>
{
    [ForceRemove | NoRemove | Delete] <sub-key> [= (s | d | m | b) 'value']
    {
        val <value-name1> = (s | d | m | b) 'value'
        val <value-name2> = (s | d | m | b) 'value'
        [ForceRemove | NoRemove | Delete] <sub-sub-key> [= (s | d | m | b) 'value']
        {
            [ForceRemove | NoRemove | Delete] <sub-sub-sub-key> = (s | d | m | b) 'value'
            val <value-name3> = (s | d | m | b) 'value'
        }
    }
}
<root-key> 最初にルートキーの名前を指定します。次のいずれかの名前、または省略形を使います。
ルートキー 省略形
HKEY_CLASSES_ROOT HKCR
HKEY_CURRENT_USER HKCU
HKEY_LOCAL_MACHINE HKLM
HKEY_USERS HKU
HKEY_PERFORMANCE_DATA HKPD
HKEY_DYN_DATA HKDD
HKEY_CURRENT_CONFIG HKCC
{ } キー内にデータを入力する時は中括弧 "{ }" を使います。
[ForceRemove | NoRemove | Delete] サブキーの名前の前に付けることが出来るフラグです。
ForceRemove は、登録の際に一旦サブキーなどの内容をすべて削除してから登録します。
NoRemove は、登録はしても削除はしないようにします。これは、CLSID や shellex キーなどで使えます。
Delete は、登録中でもサブキーを削除します。
<sub-key> [= (s | d | m | b) 'value'] <sub-key> には、サブキーの名前を入力します。' ' で囲んでも構いません。むしろ、囲むと安心してキー名を入力できます。
サブキー名以降の [ ] で囲んだ部分はオプションです ("[ ]" 記号自体は実際には入力しません)。「名前なし」の値 (レジストリエディタで「(標準)」の値) を設定したい時は、ここを記述します。

(s | d | m | b) は、s d m b のいずれかの文字を指定します ("( )" 記号自体は実際には入力しません)。

値の種類指定する値
s文字列そのまま
dDWORD 値VarUI4FromStr 関数で変換できる数値 (10 進数がいい)
mマルチ文字列「\0」で区切った文字列
bバイナリ16 進数を 2 桁ずつ区切りなしで入力した値
例:
<name> = s 'String Value'
<name> = d '12345678'
<name> = m 'String1\0String2'
<name> = b 'a4b831c492'
(もちろん ' ' は無くても構いません。ただし、s d m b の後ろは 1 文字開けてください。)
val <value-name> = (s | d | m | b) 'value' val」はキーではなく「値」を指定します。これを指定しないと、キーとして登録されます。そのあとに、<value-name> に値の名前を指定します (もちろん ' ' で囲んでも可)。これより後ろは上記と同じです。ただし、値は必ず指定します。
<sub-sub-key> サブキーの中のサブキーも可能です。なお、サブキーの中に何も入れない場合、中括弧は必要ありません。

次に、レジストリ スクリプトをリソースに追加します。なお、もともと「REGISTRY」というリソースタイプは無いので、カスタムリソース「REGISTRY」を作ることになります。

101     REGISTRY        "MyReg.rgs"

次に、上記のメソッドを呼び出します。メソッドの構文は以下のとおりです。なお、上記の 4 つのメソッドが持つ引数・戻り値はすべて同じですが、ATL と静的にリンク (ライブラリのみのリンク) した場合は S、動的にリンク (DLL にリンク) した場合は D を呼び出します。

HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(
    UINT nResID,
    BOOL bRegister,
    struct _ATL_REGMAP_ENTRY* pMapEntries = NULL
) throw();
HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(
    LPCTSTR lpszRes,
    BOOL bRegister,
    struct _ATL_REGMAP_ENTRY* pMapEntries = NULL
) throw();
nResID, lpszRes リソースの ID を指定します。
bRegister TRUE の場合はスクリプトに書かれている内容を登録します。FALSE の場合は書かれている内容をレジストリから削除します。
pMapEntries _ATL_REGMAP_ENTRY 構造体の配列を指定します。詳しくは下記をご覧ください。

_ATL_REGMAP_ENTRY の配列は、レジストリ スクリプトを登録する際に重要な役割を果たします。

レジストリ スクリプトには、「変数」を記述することが出来ます。この変数は、MS-DOS 時代の環境変数の記述方法と同じ「%」で括ることで実現できます。たとえば、スクリプト内に「%MODULE%」変数を記述すると、登録の際にこの変数がモジュールの実行パスに置き換えられます。この変数はあらかじめ登録されているもので自由に使うことが出来ます。

この変数を自由に使うために、_ATL_REGMAP_ENTRY を使用します。この配列は、以下のように作成します。

// 静的作成の場合
const _ATL_REGMAP_ENTRY entries[] = {
    { "env_name1", "value1" },
    { "env_name2", "value2" },
    .
    .
    .

    { NULL, NULL }
};

// 動的作成の場合
_ATL_REGMAP_ENTRY entries[n];

    entries[0].szKey = OLESTR("env_name1");
    // LPOLESTR 型の文字列なら、変数でも可
    entries[0].szValue = OLESTR("value1");

    entries[1].szKey = OLESTR("env_name2");
    entries[1].szValue = OLESTR("value2");
    .
    .
    .

    entries[n - 1].szKey = NULL;
    entries[n - 1].szValue = NULL;

    // 登録を実行
    _Module.UpdateRegistryFromResourceS(101, TRUE, entries);

上のコードでは、配列を entries としています。この配列をそのまま pMapEntries 引数に指定することで、独自の変数を登録することが出来ます。

注意: レジストリ スクリプトを記述する際、ファイルのサイズが 4096 バイトを超えないようにしてください。超えた場合は切り落とされます。また、登録が上手くいかない場合は、ファイルを分割させてください。

最終更新日: 2004/09/17