如何从Java访问Windows事件查看器日志数据

有什么办法从Java类访问Windows事件日志。 有没有人为此编写过任何API,并且有没有办法从远程机器访问数据?

该场景是:

我从一个控制Java进程的远程机器上运行一个进程。 这个远程进程logging东西到事件日志,我想在控制过程中看到。

提前致谢。

在Java方面,您将需要一个允许您进行本地调用的库。 Sun提供了JNI ,但听起来像是一种痛苦。 还要考虑:

在Windows端,您所使用的功能是OpenEventLog 。 这应该允许您访问远程事件日志。 另请参阅查询事件信息 。

如果这听起来不对,我也发现这个直接解析日志文件(不是我推荐的方法,但有趣的是):

http://www.j-interop.org/是一个开源的Java库,它实现了DCOM协议规范, 而不使用任何本地代码 (即,您可以使用它从非Windows客户端上运行的Java代码访问远程Windows主机上的DCOM对象)。

Microsoft通过Windows Management Instrumentation (WMI)公开大量的系统信息。 WMI可以通过DCOM进行远程访问,微软网站上也有相关的文档。 碰巧,您可以通过这个可远程访问的界面访问Windows事件日志 。

通过使用j-interop,您可以远程创建WbemScripting.SWbemLocator WMI对象的实例,然后连接到远程Windows主机上的Windows Management Instrumentation(WMI)服务。 从那里你可以提交一个查询 ,每当写一个新的事件日志条目,就会通知你。

请注意,这确实需要在远程Windows主机上正确启用和配置DCOM,并且已在任何防火墙中设置了适当的异常。 关于这方面的细节可以在线搜索,也可以参考上面的j-interop网站。

以下示例使用其NT域,主机名,用户名和密码连接到远程主机,并且位于一个循环中,并在每个事件日志条目按照由Windows登录的方式进行转储。 用户必须已被授予适当的远程DCOM访问权限,但不必是管理员。

import java.io.IOException; import java.util.logging.Level; import org.jinterop.dcom.common.JIException; import org.jinterop.dcom.common.JISystem; import org.jinterop.dcom.core.JIComserver; import org.jinterop.dcom.core.JIProgId; import org.jinterop.dcom.core.JISession; import org.jinterop.dcom.core.JIString; import org.jinterop.dcom.core.JIVariant; import org.jinterop.dcom.impls.JIObjectFactory; import org.jinterop.dcom.impls.automation.IJIDispatch; public class EventLoglistner { private static final String WMI_DEFAULT_NAMESPACE = "ROOT\\CIMV2"; private static JISession configAndConnectDCom( String domain, String user, String pass ) throws Exception { JISystem.getLogger().setLevel( Level.OFF ); try { JISystem.setInBuiltLogHandler( false ); } catch ( IOException ignored ) { ; } JISystem.setAutoRegisteration( true ); JISession dcomSession = JISession.createSession( domain, user, pass ); dcomSession.useSessionSecurity( true ); return dcomSession; } private static IJIDispatch getWmiLocator( String host, JISession dcomSession ) throws Exception { JIComserver wbemLocatorComObj = new JIComserver( JIProgId.valueOf( "WbemScripting.SWbemLocator" ), host, dcomSession ); return (IJIDispatch) JIObjectFactory.narrowObject( wbemLocatorComObj.createInstance().queryInterface( IJIDispatch.IID ) ); } private static IJIDispatch toIDispatch( JIVariant comObjectAsVariant ) throws JIException { return (IJIDispatch) JIObjectFactory.narrowObject( comObjectAsVariant.getObjectAsComObject() ); } public static void main( String[] args ) { if ( args.length != 4 ) { System.out.println( "Usage: " + EventLoglistner.class.getSimpleName() + " domain host username password" ); return; } String domain = args[ 0 ]; String host = args[ 1 ]; String user = args[ 2 ]; String pass = args[ 3 ]; JISession dcomSession = null; try { // Connect to DCOM on the remote system, and create an instance of the WbemScripting.SWbemLocator object to talk to WMI. dcomSession = configAndConnectDCom( domain, user, pass ); IJIDispatch wbemLocator = getWmiLocator( host, dcomSession ); // Invoke the "Connectserver" method on the SWbemLocator object via it's IDispatch COM pointer. We will connect to // the default ROOT\CIMV2 namespace. This will result in us having a reference to a "SWbemServices" object. JIVariant results[] = wbemLocator.callMethodA( "Connectserver", new Object[] { new JIString( host ), new JIString( WMI_DEFAULT_NAMESPACE ), JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM(), JIVariant.OPTIONAL_PARAM(), new Integer( 0 ), JIVariant.OPTIONAL_PARAM() } ); IJIDispatch wbemServices = toIDispatch( results[ 0 ] ); // Now that we have a SWbemServices DCOM object reference, we prepare a WMI Query Language (WQL) request to be informed whenever a // new instance of the "Win32_NTLogEvent" WMI class is created on the remote host. This is submitted to the remote host via the // "ExecNotificationQuery" method on SWbemServices. This gives us all events as they come in. Refer to WQL documentation to // learn how to restrict the query if you want a narrower focus. final String QUERY_FOR_ALL_LOG_EVENTS = "SELECT * FROM __InstanceCreationEvent WHERE TargetInstance ISA 'Win32_NTLogEvent'"; final int RETURN_IMMEDIATE = 16; final int FORWARD_ONLY = 32; JIVariant[] eventSourceSet = wbemServices.callMethodA( "ExecNotificationQuery", new Object[] { new JIString( QUERY_FOR_ALL_LOG_EVENTS ), new JIString( "WQL" ), new JIVariant( new Integer( RETURN_IMMEDIATE + FORWARD_ONLY ) ) } ); IJIDispatch wbemEventSource = (IJIDispatch) JIObjectFactory.narrowObject( ( eventSourceSet[ 0 ] ).getObjectAsComObject() ); // The result of the query is a SWbemEventSource object. This object exposes a method that we can call in a loop to retrieve the // next Windows Event Log entry whenever it is created. This "NextEvent" operation will block until we are given an event. // Note that you can specify timeouts, see the Microsoft documentation for more details. while ( true ) { // this blocks until an event log entry appears. JIVariant eventAsVariant = (JIVariant) ( wbemEventSource.callMethodA( "NextEvent", new Object[] { JIVariant.OPTIONAL_PARAM() } ) )[ 0 ]; IJIDispatch wbemEvent = toIDispatch( eventAsVariant ); // WMI gives us events as SWbemObject instances (a base class of any WMI object). We know in our case we asked for a specific object // type, so we will go ahead and invoke methods supported by that Win32_NTLogEvent class via the wbemEvent IDispatch pointer. // In this case, we simply call the "GetObjectText_" method that returns us the entire object as a CIM formatted string. We could, // however, ask the object for its property values via wbemEvent.get("PropertyName"). See the j-interop documentation and examples // for how to query COM properties. JIVariant objTextAsVariant = (JIVariant) ( wbemEvent.callMethodA( "GetObjectText_", new Object[] { new Integer( 1 ) } ) )[ 0 ]; String asText = objTextAsVariant.getObjectAsString().getString(); System.out.println( asText ); } } catch ( Exception e ) { e.printStackTrace(); } finally { if ( null != dcomSession ) { try { JISession.destroySession( dcomSession ); } catch ( Exception ex ) { ex.printStackTrace(); } } } } } 

阅读这篇文章 。

JNA 3.2.8有两种方法可以从Windows事件日志中读取和写入。

你可以在log4jna中看到一个写入的例子 。

这是一个读取的例子:

 EventLogIterator iter = new EventLogIterator("Application"); while(iter.hasNext()) { EventLogRecord record = iter.next(); System.out.println(record.getRecordNumber() + ": Event ID: " + record.getEventId() + ", Event Type: " + record.getType() + ", Event Source: " + record.getSource()); } 

如果您想要从远程计算机访问真正的事件日志,则必须找到一个实现EventLog远程处理协议规范的库。 不幸的是,我还没有在Java中找到任何这样的库。 然而,JCIFS和JARAPAC项目已经奠定了实施该协议的大部分基础。 协议本身(如果我没有弄错的话)运行在DCE / RPC协议之上(由JARAPAC实现),它本身运行在SMB协议之上(由JCIFS实现)。

我已经使用JCIFS和JARAPAC来实现一些EventLog的表亲协议,比如远程注册表访问。 我可能是盲目的,但是关于JARAPAC的文档似乎有些稀少。 如果你有兴趣实施这个,我可以分享一下我在学习空闲时所学到的东西!

后来!

这里有一百万(和一个)选项;)

你可以看看sigar

http://cpansearch.perl.org/src/DOUGM/hyperic-sigar-1.6.3-src/docs/javadoc/org/hyperic/sigar/win32/EventLog.html

介意许可虽然….

或者你可以快速和肮脏,只是定期执行(并捕获输出)D:> cscript.exe C:\ WINDOWS \ system32 \ eventquery.vbs / V

然后使用事件过滤参数来优化结果等… http://technet.microsoft.com/en-us/library/cc772995(WS.10).aspx