アプリケーションが一意に判断できる値を得る方法

戻る

ネットワーク上(LAN以外にPPP接続を含む)で稼動している複数のマシンで動作する 複数の同一アプリケーションを一意に識別したいときや,どのマシンの アプリケーションで作成されたデータであるかを厳密にチェックしたい場合,マシンに インストールされたアプリケーションを一意に示す識別子が必要になります.
しかし,実際に確実に一意の値を作成するのは意外と大変です. そこで,手軽にマシン固有の値を作成する方法を考えてみたいと思います.

11-1 ローカルマシンで一意の値

非常に簡単な話で,Win32 API GetCurrentProcessId や Win32 API CreateProcess で取得できるプロセスIDを利用することで,少なくともアプリケーションが 動作している間は必ず一意の値となります.しかし,アプリケーションが終了しまうと 再利用される可能性がありますので,プロセスIDに time 関数などで取得した時刻や 乱数などを含めて利用すれば,ローカルマシン内で一意の値を得ることが できます.
ファイル名を一意にするには,Win32 API GetTempFileName でファイル名を取得 すれば,作成したディレクトリ内で一意の値を取得することができます.
LAN内でも,マシン名が必ず一意である保証ができるのであれば,マシン名を含めれば 局所的に一意のIDを得ることができます.ただし,そのIDをデータファイルなどに格納 して,他の環境に移動させる可能性がある場合には利用できません.

11-2 LAN上で一意の値

●MACアドレスの利用
LANに接続しているマシンには通常,ネットワークアダプタが実装されているはずです. このアダプタには,必ず世界中で一意のMACアドレスが付けられています. この値を取得してIDに利用することにより,ネットワークアダプタが実装されている マシンであれば一意の値を作ることができます.しかし,ダイアルアップで接続される マシンに対してもIDが必要となる場合には,利用できません.
しかし,ネットワーク上で利用されることが前提をアプリケーションでは大変有効な 方法であるといえます.しかし,MACアドレスを利用すればマシンを特定することが できますが,同一マシンで複数のIDを生成する必要があるときには,MACアドレスだけ では不十分です.

●Win32 API NetBios の利用
 EthernetカードのMACアドレスは,Win32 API NetBios を利用して取得する ことができます.NetBios API は主に,IBM OS/2 などの NetBios 用に作成された アプリケーションをWindowsに移植するために利用しますが,他のWin32 API では取得 できない情報を取得することができます.また,通信機能の中でもDOS, Windows95, WindowsNT, OS/2 など多くのOSで利用できる数少ない機能の1つでもあります.

表11-1:NetBios API
#include <windows.h>
netapi32.lib
UCHAR Netbios(PNCB lpncb)
ネットワーク制御ブロック実行する

引数
PNCB lpncb ... ネットワーク制御ブロックのアドレス

戻り値
同期要求の場合 NCBの完了コード
非同期コマンドが未処理状態の場合 0

11-3 世界で一意の値

ネットワークアダプタが実装されているマシンではMACアドレスを利用すれば, 少なくともマシンを特定することができます.
しかし,ネットワークアダプタが実装されていない環境や,ローカルマシンで複数のID が必要なときには,他の方法を考える必要があります.
11-4 UUID/GUID

●UUIDとは
OLEオブジェクトやリモートプロシジャではUUID(Universally Unique Identifer)と 呼ばれる,必ず一意の値を取得して利用します.この値は,OSF/DCE で定義された アルゴリズムで取得します.このアルゴリズムを利用すればほぼ確実に世界中で一意の IDを取得することができます.
生成されたUUID/GUIDは,どのマシンでいつ取得しても必ず異なる値となります. この値を生成するアルゴリズムは,
 現在の時刻
 時計の逆進を処理するクロックシーケンスなど
 高速割り当てに対処するためのカウンタ
 ネットワークアダプタのIEEEマシンIDまたはマシンごとに異なる状態情報
から合成された値を利用します.

●UUIDとGUIDの関係
UUIDは元々RPCのインターフェースを定義されるために利用することを目的にして いますが,WindowsではこのIDをCOM(Compnent Object Model)の IID(Interface Identifer)やCLSID(Class Identifer)に利用し,これらのIDを総称して GUIDと呼んでいます.
 実際にこのIDを取得するには,Win32 RPC API UUIDCreate をるか, Win32 OLE API CoCreateGuid を利用することで取得することができます.

表11-2:UUID/GUIDを取得する API
#include <rpc.h>
rpcrt4.lib
RPC_STATUS RPC_ENTRY UuidCreate(UUID *Uuid)
UUIDを生成する

引数
UUID *Uuid ... UUIDを格納する領域を指すポインタ

戻り値
正常終了 RPC_S_OK
異常終了 RPC_S_UUID_NO_ADDRESS
(トークンリングまたはイーサネットハードウェアアドレスを 取得できなかった)
#include <windows.h>
ole32.lib
HRESULT CoCreateGuid(GUID *lpguid)
GUIDを生成する

引数
GUID *pguid ... GUIDを格納する領域を指すポインタ

戻り値
S_OK


11-5 GUIDの構造

この値は4つの部分に別れています.OSF/DCEのドキュメントを持っていないため 正確なことは分かりませんが,少なくともネットワークカードが実装されている マシンで取得したGUIDの Data4[2]〜Data4[7] はMACアドレスが設定されています.
<GUID構造体 (NSPAPI.H)>
typedef struct _GUID {
 unsigned long Data1;
 unsigned short Data2;
 unsigned short Data3;
 unsigned char Data4[8];
} GUID;
また,GUIDを何回取得しても Data4 は変化しないため Data4 はマシンを特定するため のIDと推測されます.
このため,ネットワークアダプタを持たないマシンでも GUIDのData4メンバを利用 すれば,マシンを一意に特定するIDを得ることができるようになると思われます.

図11-1:GUIDの構造

  87F97E60-0DE2-11D1-8E3D0C06C109AC3
                         ^^^^^^^^^^^ MACアドレス
  -------- ---- ---- ---------------
     ↑     ↑   ↑        ↑
     |     |   |        |
     +-----|---|--------|------ Data1
            +---|--------|------ Data2
                 +--------|------ Data3
                           +------ Data4
               ※ 取得したマシンのMACアドレス:00C06C109AC3

11-6 WindowsのプロダクトID

●プロダクトIDとCDキー
最近,Microsoft社のOSやアプリケーションをインストールするときにはプロダクト IDやCDキーの入力を要求されます.
この値を利用すれば,インストールされたWindowsも一意に認識することができるよう になります.アプリケーションがこの値を利用してもよいかもしれませんが, ユーザーの入力ミスや,複数のマシンに同じIDを設定してインストールを行うことが できます.また,レジストリエディタで簡単に変更することができますので,あまり 確実な方法ではありません.
プロダクトIDが設定されているレジストリキーには,OSバージョンなども記録されて います.しかし,ここに記録されている内容はOSの種類やバージョンによって変更 されることも考えられますので,APIで取得できる項目に関してはできるだけ,この値 を利用しないほうがよいでしょう.
・Windows95
 プロダクトID: 29896-OEM-0016482-39557
 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
 "ProductId=29896-OEM-0016482-39557"
・WindowsNT4.0
 プロダクトID: 52385-337-6714111-81322
 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
 "ProductId=52385337671411181322"

●REGEDIT.EXEとREGEDT32.EXEの違い
ところで,WindowsNTで任意のレジストリキーを検索するにはレジストリエディタ REGEDT32.EXE を利用します.しかしWindowsNT版はキーの検索しかできません. Windows95のレジストリエディタ REGEDIT.EXEはキー以外に値やデータも検索の対象に することができます.また,レジストリキーの保存をテキストファイル形式で保存する ことができるため便利に利用できます.
Window95のレジストリエディタはHKEY_DYN_DATAの操作などを除き,WindowsNTでも利用 できるようなので必要に応じてREGEDT32.EXEと使い分けるとよいでしょう.
(* Windows95のREGEDIT.EXEはWindowsNTでの動作は保証されていない.)

11-7 プログラムについて

MACアドレスとGUIDを取得を行うサンプルプログラムです. コマンドを実行すると,
D:\>unique
MAC: 00C06C109AC3
GUID: F94D3F60-0F73-11D1-8E3D0C06C109AC3
のようにMACアドレスとGUIDを表示します.

●ソースファイル
UNIQUE.EXE
 UNIQUE.C (ソースファイル)
 MAKEFILE (メイクファイル)