第 5 章 システムの実装
5.1 実装環境
表5.1の実装環境で実装を行った.
表 5.1: 実装環境
version
OS Windows2000ServicePack2
開発環境 VisualC++6.0
Database MySQL3.27.47(WindowsNT版)
DBInterface ODBC
ODBC Driver myo dbc2.50.39(NT版)
本システムはWindows2000ServicePack2上で実装を行った.開発環境はVisualC++6.0 を使用した.VisualC++を使用した理由として,WindowsAPIの呼び出しが可能であるこ とを挙げる.またユーザ入力の履歴を保存するためにデータベースとしてMySQL3.27.47
(WindowsNT版)を使用した.MySQLデータベースとの入出力インタフェースにはODBC
を使用した.MySQLのODBCド ライバにはmyodbc2.50.39(NT版)を使用した.
5.2
基本技術
本節では実装にあたって必要な知識を述べる.まず必要な用語を説明する.次にWindows 独自のAPIの説明を行う.
5.2.1
実装に関連した用語
本小節では実装方法を述べるにあたって使用するWindows独自の概念を,プロセスと スレッド,メッセージ,フック処理,ハンド ル,コールバック関数,DLLの6点について 説明する.
プロセスとスレッド
一般にMicrosoftWindowsのアプリケーションは単一プロセスで稼動している.アプリ
ケーションは複数のスレッド が平行して動作している.
基本的にアプ リケーション内でデータの共有を行うことは可能である.しかしアプ リ ケーション間でデータの共有は,あるアプリケーションがメモリ内のある部分に書き込ん だ情報を別のアプリケーションが読み取るといった単純な方法では不可能である.アプリ ケーション間の通信を行うためにメッセージを使用する.
図 5.1: プロセスとスレッド の概念図 メッセージ
MSWindowsではメッセージという概念でプロセス間通信やユーザインタフェースを実
現している.キー入力やマウスクリックをユーザが行った場合,対象のウィンド ウにキー メッセージやマウスメッセージを通知し,ウィンド ウ側がそのメッセージに対応している 手続きを実行することでマウスクリックやキーボード 入力を実現している.
図 5.2: メッセージの概念図
図5.2の例ではMS Windowsに存在するウィンド ウの右上の終了ボタンの部分でマウ
スをクリックすることによって,システムはマウスメッセージを受け取る.システムはマ ウスクリックを行ったウィンド ウにメッセージを通知する.ウィンド ウは終了ボタン上で 起きたと判断し,コールバック関数のOnDestroy関数を呼ぶ.
フック処理
しかし上記のメッセージによる通信の方法では他のアプリケーションに対して送られた メッセージの内容を知ることはできない.他のアプリケーションに対するメッセージを処 理するためにフック処理の概念を利用する.フックを利用することで本来メッセージが送 られるべきアプリケーションからメッセージを横取りし,処理を書き換えることができる.
図 5.3: フック処理の概念図
図5.3の例では,キー入力を横取りし,キー入力を独自に処理している.図5.3の場合 は再び処理をシステムに戻しているが,実際は必ずしも処理を戻す必要はない.
コールバック関数
コールバック関数は,関数ポインタをシステムに登録しておくことにより一定の条件が 起きた場合に該当する関数を実行する機構である.フック処理を行うためにはフック処理 時に処理する関数をコールバック関数として登録する必要がある.
図5.4の例では,あらかじめOnDestroy関数を登録することによって,終了メッセージ が届いた場合には自動的にシステムがOnDestroy関数を呼び出す.
ハンド ル
ハンド ルはウィンド ウ,メニュやファイルなどのインスタンスを指し示す変数で,主に ウィンド ウを識別する変数として使用される.同じアプリケーションでもアプリケーショ
図 5.4: コールバック関数の概念図
ンが起動するごとにハンド ルの値は変わるためハンド ルの値はコンピュータの利用中にわ たるウィンド ウの識別子でなく一過的な識別子として利用する.
DLL (Dynamic Link Library)
DLLはアプ リケーションでライブラリ中の関数や変数が必要となった場合にライブラ リを動的に読み込む事を可能にする機構である.関数や変数をライブラリとして保存す ることで,複数のアプ リケーションに共通して使われるような関数の実装をアプ リケー ションプログラム内にもつ必要がなくなる.またアプ リケーション外部に関数や変数を 保持することによりアプ リケーション間で同じ関数や変数を利用することができる.MS
WindowsではDLLを介してフック関数を利用することによって,全てのプロセスに対す
る入力を検出して保存する事が可能となる.
5.2.2
実装技術
本小節では実装する上で重要な技術としてSetWindowsHookEx関数と,MySQLとの インタフェースであるODBCの2点について解説する.
SetWindowsHookEx関数
本システムではユーザ入力を検出する手段としてWindows API 関数の
SetWindow-sHookEx関数を使用した.SetWindowsHookEx関数は,プロセスに対してあるメッセー
ジが送られた場合,状況に応じたコールバック関数を呼び出すために,呼び出されるべ きコールバック関数をインストールする関数である.SetWindowsHookEx関数を使用す ることによって各プロセスに送られるメッセージを捕捉し,データベースに保存するこ とができる.本システムではSetWindowsHookEx関数を全てのプロセスを対象にして入
力検出を行う必要があるのでフック関数をDLL(Dynamic Link Library)上に定義する.
SetWindowsHookEx関数の宣言は図5.5のようになっている.
HHOOK SetWindowsHookEx(
int idHook, // インストールするフックの種類
HOOKPROC lpfn, // フックプロシージャのアド レス
HINSTANCE hMod, // アプ リケーションインスタンスのハンド ル
DWORD dwThreadId // フックをインストールするスレッド のID
);
図 5.5: SetWindowsHookEx関数の宣言
本システムではidHook部分にWH CBTを使用した.このフックはコンピュータを利 用したトレーニング(CBT)アプリケーションの作成に有用なメッセージを監視するフッ クプロシージャをインストールする.HINSTANCEhModの部分にはlpfnパラメータで 指定したフック関数が置かれているDLLのハンド ルを指定する.本システムの実装では
SetWindowsHookEx関数の呼び出し元の関数とインストールされるフック関数が同じDLL
内で定義されているため,呼び出したDLLのインスタンスハンド ルを代入する.第4引 数にはフックをインストールするべきスレッド のIDを代入する.本システムでは全プロ セスへを対象に入力を検出するので0を代入する.CBTProcは表5.2のイベントを検出 する.
表 5.2: CBTProc イベントの分類
イベント名 説明
HCBTACTIVATE システムがウィンド ウをアクティブ化しようとしている
HCBTCLICKSKIPPED システムがマウスメッセージを削除した
HCBTCREATEWND ウィンド ウが作成されようとしている
HCBTDESTROYWND ウィンド ウが破棄されようとしている
HCBTKEYSKIPPED システムがキーボード メッセージを削除した
HCBTMINMAX ウィンド ウが最小化,または,最大化されようとしている
HCBTMOVESIZE ウィンド ウの移動,または,サイズ変更が行われようとしている
HCBTSETFOCUS ウィンド ウがキーボード フォーカスを受け取ろうとしている
HCBTSYSCOMMAND システムコマンド が実行されようとしている
検出されたイベントのウィンド ウハンド ルからユーザの入力が行われたウィンド ウを特 定することができる.これらのイベントを個別に処理し,取得した入力の情報をデータ ベースに格納する.
本システムのデータの格納は,プロセス間のデータ通信が容易で確実であるという理由 から,リレーショナルデータベースを利用することによって行う.データベースを使用す るにあたってODBCを使用することにより細かなデータベース固有のAPIにとらわれる ことなく実装することが可能とある.ODBCは異なるRDBSのインタフェースをラッピ ングする.ODBCを利用することによって稼動しているデータベースを意識することな くデータベースを利用することが可能となる.例えばMS SQLServerとOracleはどちら もSQL問い合わせによるデータ処理をサポートしているが,使用できるSQL問い合わせ には若干の違いがある.もしプログラムの内部でこれらのSQL問い合わせを直接行って いたならば,データベースを変更する場合,プログラムの変更を余儀なくされる.しかし
ODBCに準拠したプログラムを書いている場合,ODBCド ライバを変更するだけでデー タベースの変更が可能である.
ODBCを利用する場合,データベースに対して行う操作は大きく分けて以下の三つの 部分に分けることができる.
1. データベースに接続
2. データベースとの入出力
3. データベースとの接続解除
以下に上の3つの状況で行うべき手順をそれぞれ述べる.
データベース接続
データベースに接続する手順は次の手順となる.
1. データベース環境を取得
2. データベース接続
SQLAllocEnv ( &hEnv )
SQLAllocConnect( hEnv, &hDbc )
SQLConnect ( hDbc,
servername, SQL_NTS,
userid, SQL_NTS,
password, SQL_NTS )
図 5.6: データベース接続部 図5.6の手順でデータベースに接続する.