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

「JNA」 Event Logging API を使ってイベントログを出力する

Event Logging API を使ってイベントログを出力するサンプルを書いてみたのでメモを残しておきます。

・Event Logging API
https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa363652.aspx


以下サンプルです。

・WindowsEventReporter.java

package com.example.jna.winevent;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.WORD;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.PSID;

public class WindowsEventReporter {
	public interface Kernel32 extends Library {
		Kernel32 INSTANCE = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);

		int GetLastError();
	}

	public interface Advapi32 extends Library {
		Advapi32 INSTANCE = (Advapi32) Native.loadLibrary("advapi32", Advapi32.class);

		// event log type
		public static final WORD EVENTLOG_SUCCESS = new WORD(0x0000);
		public static final WORD EVENTLOG_AUDIT_FAILURE = new WORD(0x0010);
		public static final WORD EVENTLOG_AUDIT_SUCCESS = new WORD(0x0008);
		public static final WORD EVENTLOG_ERROR_TYPE = new WORD(0x0001);
		public static final WORD EVENTLOG_INFORMATION_TYPE = new WORD(0x0004);
		public static final WORD EVENTLOG_WARNING_TYPE = new WORD(0x0002);

		public static final WORD UI_CATEGORY = new WORD(0x00000003L);

		HANDLE RegisterEventSourceW(WString lpUNCServerName, WString lpSourceName);

		boolean DeregisterEventSource(HANDLE hEventLog);

		boolean ReportEventW(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
				WORD wNumStrings, DWORD dwDataSize, WString[] lpStrings, Pointer lpRawData);
	}

	public static void main(String[] args) {
		HANDLE hEventLog = null;
		try {
			hEventLog = Advapi32.INSTANCE.RegisterEventSourceW(null, new WString("TestProvider"));
			if (null == hEventLog) {
				System.err.println("RegisterEventSource failed. error code=" + Kernel32.INSTANCE.GetLastError());
				System.exit(-1);
			}

			WString[] s = { new WString("test event log") }; //イベントログに出力する文字列
			DWORD eventId = new DWORD(100); //イベントID
			if (!Advapi32.INSTANCE.ReportEventW(hEventLog, Advapi32.EVENTLOG_INFORMATION_TYPE, Advapi32.UI_CATEGORY,
					eventId, null, new WORD(1), new DWORD(0), s, null)) {
				System.err.println("ReportEvent failed. error code=" + Kernel32.INSTANCE.GetLastError());
				System.exit(-1);
			}

		} finally {
			if (hEventLog != null) {
				Advapi32.INSTANCE.DeregisterEventSource(hEventLog);
			}
		}
	}
}

・実行結果(イベントビューアの[詳細]タブ - [XMLで表示]から確認)

- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
  <Provider Name="TestProvider" /> 
  <EventID Qualifiers="0">100</EventID> 
  <Level>4</Level> 
  <Task>3</Task> 
  <Keywords>0x80000000000000</Keywords> 
  <TimeCreated SystemTime="2016-09-10T02:55:25.555880200Z" /> 
  <EventRecordID>5668</EventRecordID> 
  <Channel>Application</Channel> 
  <Computer>*****</Computer> 
  <Security /> 
  </System>
- <EventData>
  <Data>test event log</Data> 
  </EventData>
  </Event>


上記は文字列をイベントログに出力するサンプルになりますが、6 ~ 9 引数の指定仕方によってバイナリデータを出力することもできるっぽいですね。

・Event Logging Functions
https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa363654.aspx
・Reporting Events
https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa363680.aspx


今回は Event Logging API という Windows Server 2003, Windows XP, or Windows 2000 の OS で動作するアプリケーション向けにデザインされた API で試したみましたが、Vista 以降は Windows Event Log API になるらしいので、これ使ったサンプルもまた書いてみたいと思います。

Windows Event Log API
https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa385780.aspx


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

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