2005年08月16日

Windowsのイベントログを書き込む方法

Windowsで24時間365日稼動を保証する
ミッションクリティカルな
アプリケーションを作成する場合などに、
アプリケーションで発生する警告や致命的エラーを、
管理者がすばやく検出し対処できる様に、
適切なソリューションを提供する必要があります。

Windowsのサービスやアプリケーションが出力する
システムエラー、セキュリティ警告、アプリケーションエラーなどは、
主にイベントログに出力される仕組みが出来ています。
しかし、随時発生するイベントを、
「イベントビューア」で確認していては、
管理者の負荷はとても高く、
現実的な運用管理とほど遠いものとなります。

世の中には、Windowsのイベントログにフィルタリングを行い、
必要な情報を管理者へメールで通知するツールや、
Windows XP/Windows Server 2003から
提供された「eventtriggers」コマンドを利用し、
必要なイベントを必要なタイミングで抽出し、
任意のスクリプトを実行できる
便利な運用管理ツール類が存在します。
フィルタリングし通知するツールは別途紹介するとして、

今回は、アプリケーションで、
Windowsイベントログの利用を検討されているあなたに、
WindowsAPI関数の「ReportEvent」を
利用した具体的なソリューションを、
Delphiのサンプルプログラムで紹介します。

サンプルプログラム実行前に
以下の手順を実行してください。


@
EventLog.mcファイルをコンパイルしEventLog.rcを作成する。
MC.EXE EventLog.mc
A
EventLog.rcファイルをコンパイルしEventLog.resを作成する。
BRCC32.EXE -32 EventLog.rc
B
EventLog.resファイルをEventLogTesterUnit.pasに登録する。
{$R EventLog.RES}
C
レジストリにEventLogTesterのエントリを作成する。
・HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\
 Services\EventLog\Applicationキー配下に
 「EventLogTester」キーを作成する。
・HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\
 Services\EventLog\Application\EventLogTesterキー配下に
 名前=EventMessageFile,種類=REG_SZ,
 データ=<EventLogTester.exeのフルパス>を作成する。
・HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\
 Services\EventLog\Application\EventLogTesterキー配下に
 名前=TypesSupported,種類=REG_DWORD,
 データ=0x00000007を作成する。

全ソースは【続きを読む】をクリック!

使用例
procedure TForm1.btnReportEventClick(Sender: TObject);
const
 // イベント識別子
 EVENTID_INFOMATION = $400003E9;
 EVENTID_WARNING = $800003EA;
 EVENTID_ERROR = $C00003EB;
var
 lHdl: THandle;
 lMsg: String;
 lType,
 lEventID: Integer;
begin
 // イベントログのハンドルを取得する
 lHdl := RegisterEventSource(Nil, PChar('EventLogTester'));
 // ログに書込むイベントの種類を決定する
 case rgEventType.ItemIndex of
 0: // Information
  begin
   lType := EVENTLOG_INFORMATION_TYPE;
   lEventID := EVENTID_INFOMATION;
  end;
 1: // Warning
  begin
   lType := EVENTLOG_WARNING_TYPE;
   lEventID := EVENTID_WARNING;
  end;
 2: // Error
  begin
   lType := EVENTLOG_ERROR_TYPE;
   lEventID := EVENTID_ERROR;
  end;
 end;
 // メッセージをイベントログへ書込む
 lMsg := Format('%s', [edtEventMessage.Text]);
 ReportEvent(
  // イベントログのハンドル,
  // ログに書込むイベントの種類,
  // イベントの分類,
  // イベント識別子,
  // ユーザーセキュリティ識別子(省略可能),
  // メッセージにマージする文字列の数,
  // バイナリデータのサイズ(バイト数),
  // メッセージにマージする文字列の配列,
  // バイナリデータのアドレス

  lHdl,
  lType,
  StrToIntDef(edtEventCategory.Text,0),
  lEventID,
  Nil,
  1,
  0,
  @lMsg,
  Nil
 );
 // イベントログのハンドルを閉じる
 DeregisterEventSource(lHdl);
end;


【画面イメージ】

EventLogTester.gif

関連書籍


Copyright guy@かしらもんじ でぇ〜

続きを読む
posted by guy at 21:21 | 運用管理編

2005年08月03日

Windowsの高分解能タイマを利用し処理時間を計測する方法

あなたが業務でプログラミングを行う場合、
パフォーマンスをシビアに
要求される局面は多々あるかと思います。
闇雲にプログラムをチューニングし、
時間の無駄使いをしないためにも、
ボトルネックとなる処理を
効率よく洗出し対処することが重要になります。

処理が遅いアプリケーションを調査すると、
ほとんどの場合、2割のボトルネックが
遅い原因の8割を占めるという結論に至ります。
効率よく処理速度を向上するには、
この2割のボトルネックにメスを入れ、
他の8割はホドホドに対応するのが良いでしょう。
また運用フェーズなどでは
長期的なパフォーマンスの集計を行い、
パフォーマンスの低下がないか調べる必要もあるでしょう。

というわけで、
今回はプログラムの処理時間を計測する方法をご紹介します。
あなたのプログラムに組み込んで処理時間を計測してください。

計測方法はとても簡単です。
「QueryPerformanceFrequency」API関数を呼び出し、
高分解能パフォーマンスカウンタの
カウンタ周波数を取得します。
計測したい処理の前後で
「QueryPerformanceCounter」API関数を呼び出し、
高分解能パフォーマンスカウンタの値をそれぞれ取得します。
取得したカウンタ値の差を1000倍しカウンタ周波数で
割ってやると処理時間がミリ秒の単位で計測できます。

インストール先のハードウェアが
高分解能パフォーマンスカウンタをサポートしない場合、
関数は0を戻し計測できませんので注意が必要です。

使用例
procedure TForm1.Button1Click(Sender: TObject);
 procedure _Loop;
 var
  lCnt1,
  lCnt2,
  lCnt3: Integer;
 begin
  lCnt3 := 0;
  for lCnt1 := 1 to 10000 do
   for lCnt2 := 1 to 10000 do
    Inc(lCnt3);
 end;
var
 lSPoint,
 lEPoint,
 lFrequency: TLargeInteger;
 lElapse: Double;
begin
 // カウンタ周波数を取得します
 QueryPerformanceFrequency(lFrequency);
 // 計測開始のカウンタ値を取得します
 QueryPerformanceCounter(lSPoint);
 // 計測対象の処理です
 // 10000*10000回のループ処理を実行します
 _Loop;
 // 計測終了のカウンタ値を取得します
 QueryPerformanceCounter(lEPoint);
 // 経過時間をミリ秒単位で算出します。
 lElapse := 1000 * (lEPoint - lSPoint) / lFrequency;
 ShowMessage(Format(
  '経過時間 = %.2f (ms)', [lElapse]));
end;

関連書籍


Copyright guy@かしらもんじ でぇ〜

posted by guy at 07:01 | 運用管理編

2005年07月31日

事前に登録したプログラムを順番に終了させる方法

空の雲は厚く、郊外は緑のジャングル、
時おりスコールと雷鳴が都会慣れした我々を脅かす。
日本の梅雨と変わらない気候が重くのしかかる。
そこは赤道にほど近い東南アジアのとある場所...

先進国で生活されるほとんどの皆さんは、
水道、ガス、電気などのライフラインは
整備されいることが当たり前と思われるでしょう。
私が出張で滞在した東南アジアのライフラインは、
日本の水準では考えられないものでした。

雷が鳴るたびに電源の供給が停止し、
機関系システムが、
たびたびUPS電源のお世話になるのです。
停電も日本のように瞬停ではなく、
復旧しないこともしばしばありました。
(今では改善され良くなったと聞きますが...)

少し前置きが長くなりました。
今回は停電発生時にUPSの
自動シャットダウン機能などから実行し、
機関系システムの関連プロセスを一斉に終了させるのに便利な
WindowsのサンプルプログラムをDelphiで紹介しましょう。
OSシャットダウン前に、関連プロセスを順番に終了し、
大切なデータを保護することが目的です。

通常の行儀良いWindowsアプリケーションは、
「WM_QUIT」メッセージを受信すると終了処理を行います。
中にはははみ出し者がいるもので、
これに従わなアプリケーションもあることでしょう。

本プログラムはINIファイルに記述されたプログラム名を、
EnumWindows」、「EnumProcesses」APIの
実行結果から情報を検索し終了させます。
終了手順は、該当プロセスへ「WM_QUIT」を送信し、
相手が自主的に行儀良く終了するのを待ちます。
一定時間内に相手が終了しない場合、
TerminateProcess」を発行し強制的に終了させます。
一連の処理を実行後、本プログラムは自動で終了し、
起動から終了までの処理をログファイルに書き込みます。

処理内容
説明
@プロセスの取得
「EnumWindows」、「EnumProcesses」などのAPIを利用し、現在稼動中のプロセス情報を取得する。基本的にウィンドウを持つプロセスの情報を取得する。
AINIファイルの読込
INIファイルを読込み、終了させたいプロセスの実行モジュール名を取得する。
Bプロセスの終了
Aで読込んだ実行モジュール名を@のプロセス情報から取得し終了処理を行う。はじめ該当プロセスへ「WM_QUIT」を送信するが、一定時間以上応答が無い場合、「TerminateProcess」APIを発行し該当プロセスを強制終了する。

全ソースは【続きを読む】をクリック!

【画面イメージ】

Terminator.gif

関連書籍


Copyright guy@かしらもんじ でぇ〜

続きを読む
posted by guy at 06:39 | 運用管理編

2005年07月25日

Win32プロセス情報をまるごと取得する方法

WindowsNT、2000、XP
上で動作する各プログラムの
CPU使用率、メモリ使用量、優先順位、
ハンドル数、スレッド数などを取得するには、
どうすればよいか悩んだことかはありませんか?

Win32SDKのヘルプを見ても、
残念ですが、その解決方法は記載されておりません。
ところが、実際に各プロセスの上記情報を取得できる
非公開の(隠された)APIが存在するのです。

我々がMicrosoftOfficeと同等の
ワープロや表計算ソフトをつくったとして、
それらソフトはオリジナルよりも高速に
動作するでしょうか?
おそらく答えは「No」ではないでしょうか。
そこには我々が知り得ない
数々の非公開テクニックがあるからです。

ではさっそく、そのプログラムを公開しましょう。
今回あなたが実際にプログラムを実行して確認出来るように、
Delphiソースを、すべて公開しますから、安心してくださいね。

このプログラムは、
Windowsのタスクマネージャのプロセス一覧と
ほぼ同等の機能を持っています。
約1秒間隔で、Windowsが管理するプロセス情報から、

「NtQuerySystemInformation」

という隠れAPI関数で、各プロセスの情報を取得し、
各プロセスの一覧を作成し表示します。
あとおまけで、
OSのCPU使用率、物理メモリの使用率、
ディスクの使用率の各傾向を、
グラフでビジュアルに表示します。

全ソースは【続きを読む】をクリック!

この記事を読んで役に立ったと思うあなた、
私にビール1本おごってくださいね。(笑い)


【画面イメージ】

WTM24.gif

関連書籍

Copyright guy@かしらもんじ でぇ〜

続きを読む
posted by guy at 07:52 | 運用管理編

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は1年以上新しい記事の投稿がないブログに表示されております。