イベントログに何かを書き込みたいだけであれば、
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; } //---------------------------------------------------------------------------