イベントログの操作

イベントログに何かを書き込みたいだけであれば、

void __fastcall subEventLog(AnsiString strUSR, AnsiString strMSG, int iTYPE)
{
    //  イベントログに文字列を残す
    HANDLE hELOG;

    hELOG = ::RegisterEventSource(NULL, strUSR.c_str());
    char *buf;

    buf = (char*)malloc(strMSG.Length() + 2);
    strcpy(buf, strMSG.c_str());

    if (iTYPE == 0)	{
        ::ReportEvent(hELOG, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char**)&buf, NULL);
    } else {
        ::ReportEvent(hELOG, EVENTLOG_ERROR_TYPE, 0, 0, NULL, 1, 0, (const char**)&buf, NULL);
    }

    free(buf);
}

こんな感じで書き込むことができます。
(ただし、自由な文字を書き込むにはもっといろいろなことをやらないといけません。ここでやっているのは、簡易的にやっているだけなので、「次の文字列が含まれています」パターンでの表示になります。)

しかし、読み込み等まで含めてやるために、クラスを一つ定義して使用しております。
これだとちゃんと読める日本語でイベントログを読むことができます。

ヘッダー部分

//---------------------------------------------------------------------------
//            イベントログの内容を管理するオブジェクト
//                                                            by Shue
//                                                            2006.02.12
//---------------------------------------------------------------------------
#ifndef TswEVTLOGH
#define TswEVTLOGH

#define        swEV_APP            0        //    アプリケーションログ
#define        swEV_SEC            1        //    監査ログ
#define        swEV_SYS            2        //    システムログ

#define        swLOG_ERROR            1        //    エラー
#define     swLOG_WARNING        2        //    警告
#define     swLOG_INFORMATION    4        //    情報
#define        swLOG_AUDIT_SUCCESS    8        //    監査成功
#define        swLOG_AUDIT_FAILURE    16        //    監査失敗

//---------------------------------------------------------------------------
struct swEVTLOG_DATA
{
    unsigned long iRECORD_NUM;
    AnsiString strGEN_TIME;
    AnsiString strWRT_TIME;
    AnsiString strSOURCE;
    unsigned long iEVT_ID;
    unsigned long iEVT_TYPE;
    AnsiString strEVT_TYPE;
    AnsiString strUSER;
    AnsiString strLOG_STR;
    AnsiString strMESSAGE;
    unsigned long iCATEGORY;
    AnsiString strCATEGORY;
    unsigned long iDATA_LEN;
    char *cDATA;
};
//---------------------------------------------------------------------------
class TswEVTLOG : public TObject
{
public:
    __fastcall TswEVTLOG(int iTYPE, bool bFWD);
    __fastcall ~TswEVTLOG();

    bool __fastcall GetFirstLog();
    bool __fastcall GetLastLog();
    bool __fastcall GetNextLog();
    bool __fastcall GetPreviousLog();
    bool __fastcall WriteLog(int iTYPE, int iTYPE2, AnsiString strMSG, AnsiString strUSR);

    swEVTLOG_DATA *swED;        //    データ収受バッファ

private:
    bool __fastcall OpenLog();
    TDateTime __fastcall ExchangeTime_T(int iTIME);
    AnsiString __fastcall GetEvtType(int iTYPE);
    bool __fastcall ParseData();
    AnsiString __fastcall GetCategory(AnsiString strSOURCE, unsigned long lCAT);
    AnsiString __fastcall GetFullMessage(AnsiString strSOURCE, char **cMSG, unsigned long lID);

    HANDLE hEVT;

    EVENTLOGRECORD *elrDAT;
    unsigned long iNEXT_SIZE;                //    次のデータを読むのに必要なメモリ
    unsigned long iTHIS_SIZE;                 //    今確保しているメモリ
    int iLOG_TYPE;                          //    開いているログの種類
    bool bFWDFLG;                            //    どちら向きに読むか

};
//---------------------------------------------------------------------------
#endif


C++本体部分

//--------------------------------------------------------------------------
//            イベントログの内容を管理するオブジェクト
//                                                            by Shue
//                                                            2006.02.12
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <alloc.h>
#include <mem.h>
#include <registry.hpp>
#include <windows.h>

#include "TswEVTLOG.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
__fastcall TswEVTLOG::TswEVTLOG(int iTYPE, bool bFWD)
{
    //--------------------------------------------------------
    //    コンストラクタ
    //        引数:iTYPE --- イベントログのタイプを指定する
    //                swEV_APP --- Application
    //                swEV_SEC --- Security
    //                swEV_SYS --- System
    //              bFWD ---- データを読み込む方向を指定する
    //                true ------- 古いものから順
    //                false ------ 新しいものから順
    //--------------------------------------------------------

    //    データ交換用バッファを確保
    swED = new swEVTLOG_DATA;
    swED->cDATA = NULL;
    elrDAT = (EVENTLOGRECORD*)malloc(1);
    iTHIS_SIZE = 1;
    hEVT = NULL;

    //    パラメータを保存
    iLOG_TYPE = iTYPE;
    bFWDFLG = bFWD;

    //    とりあえず先頭のイベントを読んでおく
    if (!GetFirstLog())    {
        throw("Error");
    }
}
//---------------------------------------------------------------------------
__fastcall TswEVTLOG::~TswEVTLOG()
{
    //    デストラクタ

    //    データ交換用バッファを解放
    free(swED->cDATA);
    delete swED;
    free(elrDAT);

    //    ハンドルを閉じる
    if (hEVT != NULL)    {
        ::CloseEventLog(hEVT);
    }
}
//---------------------------------------------------------------------------
bool __fastcall TswEVTLOG::GetFirstLog()
{
    //    先頭(最古)のログを取得する
    unsigned long lTMP, lDMY;

    try    {
        //    イベントログを開いている場合は一旦閉じる
        if (hEVT != NULL)    {
            ::CloseEventLog(hEVT);
        }

        //    改めてログを開く
        if (OpenLog())    {
            //    作成時のパラメータで順読みか逆読みか決定
            if (bFWDFLG)    {
                lTMP = EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ;
            } else {
                lTMP = EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ;
            }

            //    必ず失敗するように最初は1バイトのバッファで実行
            free(elrDAT);
            elrDAT = (EVENTLOGRECORD*)malloc(1);
            iTHIS_SIZE = 1;
            if (!::ReadEventLog(hEVT, lTMP, 0, elrDAT, iTHIS_SIZE, &lDMY, &iNEXT_SIZE))        {
                //    必要なサイズを定義しなおして読み直す
                free(elrDAT);
                elrDAT = (EVENTLOGRECORD*)malloc(iNEXT_SIZE);
                iTHIS_SIZE = iNEXT_SIZE;
                ::CloseEventLog(hEVT);
                if (OpenLog())    {
                    if (!::ReadEventLog(hEVT, lTMP, 0, elrDAT, iTHIS_SIZE, &lDMY, &iNEXT_SIZE))        {
                        //    これで読めなければ例外送出
                        throw("Error");
                    }
                } else {
                    //    ログが開けなかった
                    throw("Error");
                }
            }

            //    データを転記する
            ParseData();
        } else {
            return false;
        }
    }
    catch(...)    {
        return false;
    }

    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TswEVTLOG::GetNextLog()
{
    //    次のログを読む
    unsigned long lTMP, lDMY;

    try    {
        //    作成時のパラメータで順読みか逆読みか決定
        if (bFWDFLG)    {
            lTMP = EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ;
        } else {
            lTMP = EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ;
        }

        //    必ず失敗するよう1バイトのバッファで実行
        free(elrDAT);
        elrDAT = (EVENTLOGRECORD*)malloc(1);
        iTHIS_SIZE = 1;

        if (!::ReadEventLog(hEVT, lTMP, 0, elrDAT, iTHIS_SIZE, &lDMY, &iNEXT_SIZE))        {
            //    読めなかった場合はサイズを定義しなおして読み直す
            free(elrDAT);
            elrDAT = (EVENTLOGRECORD*)malloc(iNEXT_SIZE);
            iTHIS_SIZE = iNEXT_SIZE;
            if (!::ReadEventLog(hEVT, lTMP, 0, elrDAT, iTHIS_SIZE, &lDMY, &iNEXT_SIZE))        {
                //    これで読めなければ例外送出
                throw("Error");
            }
        }

        //    データを転記する
        if (!ParseData())    {
            throw("Error");
        }
    }
    catch(...)    {
        return false;
    }

    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TswEVTLOG::WriteLog(int iTYPE, int iTYPE2, AnsiString strMSG, AnsiString strUSR)
{
    //  イベントログにログを残す
    //    引数:  iTYPE ---- ログ種別 swEV_APP / swEV_SEC / swEV_SYS
    //            iTYPE2 --- イベント種別 swLOG_ERROR〜swLOG_AUDIT_FAILURE
    //            strMSG --- 追加メッセージ
    //            strUSR --- ユーザ

    char *cBUF;
    HANDLE hELOG;

    try    {
        hELOG = ::RegisterEventSource(NULL, strUSR.c_str());

        cBUF = (char*)malloc(strMSG.Length() + 2);
        strcpy(cBUF, strMSG.c_str());

        ::ReportEvent(hELOG, iTYPE, 0, 0, NULL, 1, 0, (const char**)&cBUF, NULL);

        free(cBUF);

        return true;
    }
    catch(...)    {
        return false;
    }
}
//---------------------------------------------------------------------------
bool __fastcall TswEVTLOG::OpenLog()
{
    //    イベントログを開く
    try    {
        switch (iLOG_TYPE)    {
            case 1:        //    Security
                hEVT = ::OpenEventLog(NULL, "Security");
                break;
            case 2:        //    System
                hEVT = ::OpenEventLog(NULL, "System");
                break;
            default:    //    Application
                hEVT = ::OpenEventLog(NULL, "Application");
        }
        if (hEVT == NULL)    {
            //    イベントログを開けられなかった
            throw("Error");
        }
    }
    catch(...)    {
        return false;
    }

    return true;
}
//---------------------------------------------------------------------------
TDateTime __fastcall TswEVTLOG::ExchangeTime_T(int iTIME)
{
    //    time_tで表される日付を文字列に変換する
    int iHH, iMM, iSS, iDD;
    TDateTime dtRET = 25569;    //    1970/01/01にしておく

    //    日本の時間にする
    iTIME += 9 * 3600;

    //    それぞれ求める
    iDD = iTIME / (3600 * 24);
    iTIME = iTIME % (3600 * 24);
    iHH = iTIME / 3600;
    iTIME = iTIME % 3600;
    iMM = iTIME / 60;
    iSS = iTIME % 60;
    dtRET += iDD;
    dtRET += EncodeTime(iHH, iMM, iSS, 0);

    return dtRET;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TswEVTLOG::GetEvtType(int iTYPE)
{
    //    指定コードのイベントログタイプを日本語文字列で返す
    switch (iTYPE)    {
        case EVENTLOG_ERROR_TYPE:        return "エラー";
        case EVENTLOG_WARNING_TYPE:        return "警告";
        case EVENTLOG_INFORMATION_TYPE:    return "情報";
        case EVENTLOG_AUDIT_SUCCESS:    return "成功";
        case EVENTLOG_AUDIT_FAILURE:    return "失敗";
        default:                        return "不明";
    }
}
//---------------------------------------------------------------------------
bool __fastcall TswEVTLOG::ParseData()
{
    //    バッファ間の転記を実施
    char cNAM[256], cDOM[256], *cTMP, *cTMP2, *cTMP3;
    SID_NAME_USE snuTMP;
    AnsiString strUSER, strMSG;
    int iSIZE;
    unsigned long lNAM, lDOM;
    PSID *psSID;

    try    {
        //    ユーザ名を先に求めておく
        strUSER = "不明";
        if (elrDAT->UserSidLength > 0)    {
            cTMP = (char*)elrDAT;
            cTMP += elrDAT->UserSidOffset;
            psSID = (PSID*)malloc(elrDAT->UserSidLength + 1);
            memset(psSID, 0, elrDAT->UserSidLength + 1);
            memcpy(psSID, cTMP, elrDAT->UserSidLength);

            lNAM = lDOM = 256;
            if (!::LookupAccountSid(NULL, psSID, cNAM, &lNAM, cDOM, &lDOM, &snuTMP))    {
                //    エラー
                throw("Error");
            }
            strUSER = AnsiString(cDOM) + "\\" + AnsiString(cNAM);
        }

        //    ログ中の文字列を取得
        cTMP3 = (char*)elrDAT;
        cTMP3 += elrDAT->StringOffset;
        strMSG = AnsiString(cTMP3);

        //    データを指すポインタを作る
        if (elrDAT->DataLength > 0)    {
            cTMP = (char*)elrDAT;
            cTMP += elrDAT->DataOffset;
        } else {
            cTMP = NULL;
        }

        //    ソース名を取得する
        cTMP2 = (char*)elrDAT;
        cTMP2 += (sizeof(EVENTLOGRECORD));

        //    転記をする
        swED->iRECORD_NUM = elrDAT->RecordNumber;
        swED->strGEN_TIME = ExchangeTime_T(elrDAT->TimeGenerated).FormatString("YYYY/MM/DD HH:NN:SS");
        swED->strWRT_TIME = ExchangeTime_T(elrDAT->TimeWritten).FormatString("YYYY/MM/DD HH:NN:SS");
        swED->strSOURCE = AnsiString(cTMP2);
        swED->iEVT_ID = elrDAT->EventID & 0xffff;
        swED->iEVT_TYPE = elrDAT->EventType;
        swED->strEVT_TYPE = GetEvtType(swED->iEVT_TYPE);
        swED->strUSER = strUSER;
        swED->strLOG_STR = strMSG;
        swED->iCATEGORY = elrDAT->EventCategory;
        swED->strCATEGORY = GetCategory(swED->strSOURCE, elrDAT->EventCategory);
        swED->strMESSAGE = GetFullMessage(swED->strSOURCE, &cTMP3, elrDAT->EventID);
        swED->iDATA_LEN = elrDAT->DataLength;
        if (swED->iDATA_LEN > 0)    {
            swED->cDATA = (char*)malloc(swED->iDATA_LEN + 1);
            memcpy(swED->cDATA, cTMP, swED->iDATA_LEN);
        }
    }
    catch(...)    {
        return false;
    }

    return true;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TswEVTLOG::GetCategory(AnsiString strSOURCE, unsigned long lCAT)
{
    //    パラメータから、カテゴリを取得する
    TRegistry *rgTMP;
    AnsiString strKEY, strRET = "";
    AnsiString strMOD;
    HANDLE hMOD;
    char *cBUF, cPATH[MAX_PATH];

    try    {
        //    ソース名からメッセージのモジュールファイルを検索する
        switch (iLOG_TYPE)    {
            case 1:        //    Security
                strKEY = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Security\\";
                break;
            case 2:        //    System
                strKEY = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System\\";
                break;
            default:    //    Application
                strKEY = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\";
        }
        strKEY += strSOURCE;
        rgTMP = new TRegistry;
        rgTMP->RootKey = HKEY_LOCAL_MACHINE;
        rgTMP->OpenKeyReadOnly(strKEY);
        strMOD = rgTMP->ReadString("CategoryMessageFile");
        rgTMP->CloseKey();
        delete rgTMP;

        //    モジュールへのパスを環境変数から展開しておく
        ExpandEnvironmentStrings(strMOD.c_str(), cPATH, MAX_PATH);
        strMOD = AnsiString(cPATH);

        //    モジュールファイルをロードしてメッセージを取得する
        if (!strMOD.Trim().IsEmpty())    {
            hMOD = ::LoadLibraryEx(strMOD.c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
            if (hMOD != NULL)    {
                //    メッセージを取得
                cBUF = NULL;
                ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
                        hMOD, lCAT, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), cBUF, 0, NULL);
                if (cBUF != NULL)    {
                    strRET = AnsiString(cBUF);
                    free(cBUF);
                }
            }

            //    後処理
            if (hMOD != NULL)    {
                ::FreeLibrary(hMOD);
            }
        }
    }
    catch(...)    {
        strRET = "";
    }

    return strRET;
}

//---------------------------------------------------------------------------
AnsiString __fastcall TswEVTLOG::GetFullMessage(AnsiString strSOURCE, char **cMSG, unsigned long lID)
{
    //    パラメータから、イベントログのメッセージを取得する
    TRegistry *rgTMP;
    AnsiString strKEY, strRET = "";
    AnsiString strMOD, strCAT;
    HANDLE hMOD;
    char *cBUF, cPATH[MAX_PATH];

    try    {
        //    ソース名からメッセージのモジュールファイルを検索する
        switch (iLOG_TYPE)    {
            case 1:        //    Security
                strKEY = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Security\\";
                break;
            case 2:        //    System
                strKEY = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System\\";
                break;
            default:    //    Application
                strKEY = "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\";
        }
        strKEY += strSOURCE;
        rgTMP = new TRegistry;
        rgTMP->RootKey = HKEY_LOCAL_MACHINE;
        rgTMP->OpenKeyReadOnly(strKEY);
        strMOD = rgTMP->ReadString("EventMessageFile");
        rgTMP->CloseKey();
        delete rgTMP;

        //    モジュールへのパスを環境変数から展開しておく
        ExpandEnvironmentStrings(strMOD.c_str(), cPATH, MAX_PATH);
        strMOD = AnsiString(cPATH);

        //    モジュールファイルをロードしてメッセージを取得する
        if (!strMOD.Trim().IsEmpty())    {
            hMOD = ::LoadLibraryEx(strMOD.c_str(), NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
            if (hMOD != NULL)    {
                //    メッセージを取得
                //cBUF = NULL;
                cBUF = NULL;
                ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY
                            | FORMAT_MESSAGE_FROM_SYSTEM, hMOD, lID, 0, (LPTSTR)&cBUF, 0, (va_list*)cMSG);

                if (cBUF != NULL)    {
                    strRET = AnsiString(cBUF);
                    LocalFree(cBUF);
                }
            }

            //    後処理
            if (hMOD != NULL)    {
                ::FreeLibrary(hMOD);
            }
        }
    }
    catch(...)    {
        strRET = "";
    }

    return strRET;
}
//---------------------------------------------------------------------------

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2012-12-09 (日) 22:30:50