2008-11-21 42 views
13

? Hay alguna forma de acceder al Registro de eventos de Windows desde una clase Java. ¿Alguien ha escrito alguna API para esto, y habría alguna forma de acceder a los datos desde una máquina remota?¿Cómo puedo acceder a los datos de registro del Visor de eventos de Windows desde Java

El escenario es:

corro un proceso en una máquina remota, a partir de un proceso de Java controlar. Este proceso remoto registra cosas en el Registro de eventos, que quiero poder ver en el proceso de control.

Gracias de antemano.

Respuesta

9

En el lado de Java, necesitará una biblioteca que le permita hacer llamadas nativas. Sun ofrece JNI, pero suena como una especie de dolor. También considere:

En el lado de Windows, la función que está buscando es OpenEventLog. Esto debería permitirle acceder a un registro de eventos remoto. Vea también Querying for Event Information.

Si eso no suena bien, también encontré esto para analizar los archivos de registro directamente (no es un enfoque que yo recomiendo, pero interesante, no obstante):

1

Si desea acceder al registro de eventos verdaderos desde una máquina remota, tendrá que encontrar una biblioteca que implemente el EventLog Remoting Protocol Specification. Lamentablemente, aún no he encontrado ninguna biblioteca de ese tipo en Java. Sin embargo, gran parte de la base para implementar este protocolo ya ha sido establecida por los proyectos JCIFS y JARAPAC. El protocolo en sí (si no me equivoco) se ejecuta sobre el protocolo DCE/RPC (implementado por JARAPAC) que se ejecuta sobre el protocolo SMB (implementado por JCIFS).

Ya he estado usando JCIFS y JARAPAC para implementar algunos de los protocolos de primos de EventLog, como el acceso de registro remoto. Puede que esté ciego, pero la documentación parecía un poco escasa con respecto a JARAPAC. Si está interesado en implementar esto, puedo compartir con usted lo que aprendí cuando tenga tiempo libre.

¡Más tarde!

17

http://www.j-interop.org/ es una biblioteca de Java de código abierto que implementa la especificación del protocolo DCOM sin utilizar ningún código nativo. (es decir, puede usarlo para acceder a objetos DCOM en un host remoto de Windows desde código Java que se ejecuta en un cliente que no es de Windows).

Microsoft expone una gran cantidad de información del sistema a través de Windows Management Instrumentation (WMI). WMI es accesible de forma remota a través de DCOM, y existe documentación considerable sobre el tema en el sitio de Microsoft. Da la casualidad de que puede acceder al Windows Event Logs a través de esta interfaz remotamente accesible.

Al usar j-interop, puede crear una instancia del objeto WMI WbemScripting.SWbemLocator de forma remota y luego conectarse a los servicios de Instrumental de administración de Windows (WMI) en el host remoto de Windows. Desde allí, puede enviar un query que le informará cada vez que se escriba una nueva entrada de registro de eventos.

Tenga en cuenta que esto requiere que DCOM esté habilitado y configurado correctamente en el host remoto de Windows, y que se hayan configurado las excepciones adecuadas en cualquier firewall. Los detalles sobre esto se pueden buscar en línea, y también se hace referencia desde el sitio j-interop, arriba.

El siguiente ejemplo se conecta a un host remoto usando su dominio NT, nombre de host, un nombre de usuario y una contraseña, y se ubica en un bucle, volcando cada entrada de registro de eventos cuando son registradas por Windows. El usuario debe haber obtenido los permisos de acceso a DCOM remotos adecuados, pero no tiene que ser un administrador.

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 EventLogListener 
{ 

    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: " + EventLogListener.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(); 
       } 
      } 
     } 
    } 

} 

~

1

hay un millón (y uno) opciones aquí;)

usted podría mirar a sigar

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

cuenta la concesión de licencias, aunque ....

o puede ser rápido y sucio y solo periodi camente ejecutar (y capturar la salida) D:> cscript.exe c: \ WINDOWS \ system32 \ Eventquery.vbs/v

a continuación, utilizar un filtrado de eventos params para refinar los resultados, etc ... http://technet.microsoft.com/en-us/library/cc772995(WS.10).aspx

6

Lee this article.

JNA 3.2.8 tiene ambos métodos para leer y escribir desde el registro de eventos de Windows.

Puede ver un ejemplo de escritura en log4jna.

He aquí un ejemplo de lectura:

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()); 
} 
Cuestiones relacionadas