The Grimoire of Nonsense

個人的なメモを残すブログ

イベントログを一括で削除する

イベントログをいちいち手で消すのは面倒なので一括でクリアするときのメモ。
レジストリ

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Channels

に登録されているエントリをEvtClearLog()*1を用いて削除する

一応僕が書いたコードが以下。
2015/07/11追記 SlTchar.hが抜けてたので追加しました。
ここの駄文もぐちゃぐちゃなので近いうちに整理したいです……。
SlTchar.h

#pragma once

#include <iostream>
#include <regex>
#include <tchar.h>

namespace std
{
    typedef basic_ios<TCHAR, char_traits<TCHAR> > _tios;
	typedef basic_streambuf<TCHAR, char_traits<TCHAR> > _tstreambuf;
	typedef basic_istream<TCHAR, char_traits<TCHAR> > _tistream;
	typedef basic_ostream<TCHAR, char_traits<TCHAR> > _tostream;
	typedef basic_iostream<TCHAR, char_traits<TCHAR> > _tiostream;
	typedef basic_stringbuf<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > _tstringbuf;
	typedef basic_istringstream<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > _tistringstream;
	typedef basic_ostringstream<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > _tostringstream;
	typedef basic_stringstream<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > _tstringstream;
	typedef basic_filebuf<TCHAR, char_traits<TCHAR> > _tfilebuf;
	typedef basic_ifstream<TCHAR, char_traits<TCHAR> > _tifstream;
	typedef basic_ofstream<TCHAR, char_traits<TCHAR> > _tofstream;
	typedef basic_fstream<TCHAR, char_traits<TCHAR> > _tfstream;

	// string対応
	typedef std::basic_string<TCHAR> _tstring;

	// regex対応
	typedef std::basic_regex<TCHAR> _tregex;
	typedef std::match_results<TCHAR*> _tmatch;
	typedef std::match_results<_tstring::const_iterator> _tsmatch;

#if defined(UNICODE) || defined(_UNICODE)
	#define _tcout std::wcout
	#define _tcerr std::wcerr
	#define _tclog std::wclog
	#define _tcin std::wcin
#else
	#define _tcout std::cout
	#define _tcerr std::cerr
	#define _tclog std::clog
	#define _tcin std::cin
#endif
}

Main.cpp

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <clocale>
#include "SlTchar.h"
#include <Windows.h>
#include <WinEvt.h>
#include <Shlobj.h>
#include <VersionHelpers.h>
#pragma comment(lib, "Wevtapi.lib")

using namespace std;

namespace
{
	typedef vector<_tstring> LogArray;

	// レジストリからエントリを拾う関数
	bool getLogEntries(LogArray &logArray)
	{
		const TCHAR *entry[] = {_T("SYSTEM\\CurrentControlSet\\services\\eventlog"), _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Channels")};
		const int entrySize = sizeof(entry) / sizeof(entry[0]);

		for(int i = 0; i < entrySize; i++) {
			HKEY hKey = nullptr;
			int index = 0;

			// レジストリを開いてみる
			if(FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, entry[i], 0, KEY_READ | KEY_WOW64_64KEY, &hKey))) {
				_tprintf(_T("Error: レジストリキー %s が開けなかった\n"), entry[i]);
				return false;
			}

			// 開けれたらループして取得
			while(true) {
				LONG hRes = 0;
				TCHAR buffer[MAX_PATH] = {0};
				DWORD bufferSize = MAX_PATH - 1;
				FILETIME tmp = {0};

				// キーを列挙してもらう
				hRes = RegEnumKeyEx(hKey, index, buffer, &bufferSize, nullptr, nullptr, nullptr, &tmp);

				// 最後まで見れたらお終い
				if(hRes == ERROR_NO_MORE_ITEMS) break;

				// エラーなら終了
				if(FAILED(hRes)) {
					_tprintf(_T("Error: エントリの列挙に失敗\n"));
					RegCloseKey(hKey);
					return false;
				}

				// 配列へ格納!
				logArray.push_back(buffer);

				// インクリメント!
				index++;
			}
			RegCloseKey(hKey);
		}

		return true;
	}

	// イベントログを空にする
	bool myClearEventLog(const _tstring &logName)
	{
#if !defined(UNICODE) || !defined(_UNICODE)
		wchar_t wLogName[MAX_PATH] = {0};
		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, logName.c_str(), -1, wLogName, MAX_PATH - 1);

		_tprintf(_T("EvtClearLog: %s\n"), logName.c_str());

		if(FAILED(EvtClearLog(nullptr, wLogName, nullptr, 0))) {
			_tprintf(_T("Error: %s の削除に失敗\n"), wLogName);
			return false;
		}
#else
		_tprintf(_T("EvtClearLog: %s\n"), logName.c_str());

		if(FAILED(EvtClearLog(nullptr, logName.c_str(), nullptr, 0))) {
			_tprintf(_T("Error: %s の削除に失敗\n"), logName.c_str());
			return false;
		}
#endif
		return true;
	}

	// Windowsのバージョンをチェックする関数
	bool checkWinVersion()
	{
		return IsWindowsVersionOrGreater(6, 0, 0) == TRUE;
	}
}

int _tmain(const int argc, const _TCHAR **argv)
{
	LogArray logArray;

	_tsetlocale(LC_ALL, _T(""));

	if(!checkWinVersion()) {
		_tprintf(_T("Error: Windows Vista(NT 6.0)以降で実行する必要があります\n"));
		return -1;
	}

	if(!IsUserAnAdmin()) {
		_tprintf(_T("Error: 管理者として起動する必要があります\n"));
		return -1;
	}

	if(!getLogEntries(logArray)) return -2;

	// 体裁のためだけにソート
	sort(logArray.begin(), logArray.end());

	// Systemは最後にするの
	logArray.erase(remove(logArray.begin(), logArray.end(), _T("System")), logArray.end());

	// ログを削除してみる
	for(const _tstring name : logArray)
		myClearEventLog(name);

	// System削除ォ!
	myClearEventLog(_T("System"));

	return 0;
}

*1:Windows Vita以降にあるAPI