読者です 読者をやめる 読者になる 読者になる

JNAからWindows Event Log APIを呼び出してイベントログを取得してみる(ブックマーク利用その2)

以下のエントリーでブックマークを利用したサンプルを書いてみましたが、このサンプルだとブックマークが存在しない、かつ、EvtQuery関数に渡すクエリにマッチするイベントログが存在しなかった場合にブックマークが作成されません(「//ブックマーク保存処理」の箇所の EvtNext関数でエラーになる)。

a4dosanddos.hatenablog.com


要件によりけりで難しいところですが、「ブックマークが存在しなかった場合は最後のイベントログのレコードIDでとりあえずブックマーク作ってしまう」という感じだと、以下の init() のようなメソッドを用意することが検討できるかと思います。以下の init() では Application、System チャネルの最後のレコードID をブックマークするという感じになってます。
※ createInitQuery() でクエリを作ってますが、

「<QueryList><Query><Select Path='Application'>*</Select><Select Path='System'>*</Select></Query></QueryList>」なクエリができてきます。Application、System チャネルのイベントログ全部取ってくるという感じです。

呼び出し側はブックマークが存在しなかった場合は以下の init() を呼び出す、存在した場合はブックマーク使った処理を行うという感じになりますかね。

※ renderEvent()、saveBookmarkFile() は上記のエントリーのサンプルを参照ください。

	private void init() {
		String query = createInitQuery(Arrays.asList(new String[] { "Application", "System" }));
		HANDLE hResult = null;
		HANDLE hBookmark = null;
		try {
			WString wQuery = new WString(query);
			hResult = Wevtapi.INSTANCE.EvtQuery(null, null, wQuery,
					Wevtapi.INSTANCE.EvtQueryChannelPath | Wevtapi.INSTANCE.EvtQueryTolerateQueryErrors);
			if (hResult == null)
				throw new Exception("EvtQuery Error errorCode=" + getLastErrorWrapper());

			if (!Wevtapi.INSTANCE.EvtSeek(hResult, new WinDef.LONGLONG(0), null, 0,
					Wevtapi.INSTANCE.EvtSeekRelativeToLast))
				throw new Exception("EvtSeek Error errorCode=" + getLastErrorWrapper());

			HANDLE[] saveHandles = new HANDLE[1];
			IntByReference intRef = new IntByReference(0);
			if (!Wevtapi.INSTANCE.EvtNext(hResult, 1, saveHandles, 0, 0, intRef))
				throw new Exception("EvtNext Error errorCode=" + getLastErrorWrapper());

			hBookmark = Wevtapi.INSTANCE.EvtCreateBookmark(null);
			if (hBookmark == null)
				throw new Exception("EvtCreateBookmark Error errorCode=" + getLastErrorWrapper());

			if (!Wevtapi.INSTANCE.EvtUpdateBookmark(hBookmark, saveHandles[0]))
				throw new Exception("EvtUpdateBookmark Error errorCode=" + getLastErrorWrapper());

			String saveBookmarkString = renderEvent(hBookmark, Wevtapi.INSTANCE.EvtRenderBookmark);
			saveBookmarkFile(fileName, saveBookmarkString);

		} catch (Exception e) {
			System.err.println("init() Error msg=" + e.getMessage());
		} finally {
			if (hResult != null)
				Wevtapi.INSTANCE.EvtClose(hResult);
			if (hBookmark != null)
				Wevtapi.INSTANCE.EvtClose(hBookmark);
		}
	}

	private String createInitQuery(List<String> channels) {
		StringBuffer sb = new StringBuffer();
		sb.append("<QueryList><Query>");
		for (String c : channels) {
			sb.append("<Select Path='");
			sb.append(c);
			sb.append("'>*</Select>");
		}
		sb.append("</Query></QueryList>");
		return sb.toString();
	}


簡単ですが、以上になります。

[環境情報]
Windows 10
Java SE 8 Update 92
JNA 4.2.2