Как получить доступ к данным журнала Windows Event Viewer из Java - PullRequest
13 голосов
/ 22 ноября 2008

Есть ли способ получить доступ к журналу событий Windows из класса Java. Кто-нибудь написал для этого какие-либо API, и есть ли какой-нибудь способ получить доступ к данным с удаленного компьютера?

Сценарий:

Я запускаю процесс на удаленной машине из контролирующего процесса Java. Этот удаленный процесс записывает данные в журнал событий, который я хочу видеть в процессе управления.

Заранее спасибо.

Ответы [ 5 ]

17 голосов
/ 24 апреля 2009

http://www.j -interop.org / - это библиотека Java с открытым исходным кодом, которая реализует спецификацию протокола DCOM без использования собственного кода . (то есть вы можете использовать его для доступа к объектам DCOM на удаленном хосте Windows из кода Java, запущенного на клиенте, отличном от Windows).

Microsoft предоставляет множество системной информации через Инструментарий управления Windows (WMI). WMI доступен удаленно через DCOM, и на сайте Microsoft имеется немало документации по этому вопросу. Когда это происходит, вы можете получить доступ к Журналам событий Windows через этот удаленно доступный интерфейс.

Используя j-interop, вы можете удаленно создать экземпляр объекта WMI WbemScripting.SWbemLocator , а затем подключиться к службам инструментария управления Windows (WMI) на удаленном хосте Windows. Оттуда вы можете отправить запрос , который будет информировать вас всякий раз, когда пишется новая запись в журнале событий.

Обратите внимание, что для этого требуется, чтобы DCOM был правильно включен и настроен на удаленном хосте Windows, и чтобы в любых брандмауэрах были установлены соответствующие исключения. Подробности об этом можно найти в Интернете, а также ссылки на сайте j-interop выше.

Следующий пример подключается к удаленному хосту, используя его домен NT, имя хоста, имя пользователя и пароль, и зацикливается на каждой записи журнала событий, когда они регистрируются окнами. Пользователю должны быть предоставлены соответствующие разрешения на удаленный доступ к 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 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();
                }
            }
        }
    }

}

~

9 голосов
/ 22 ноября 2008

На стороне Java вам понадобится библиотека, которая позволяет вам делать собственные вызовы. Sun предлагает JNI , но это звучит как боль. Также учтите:

На стороне Windows функция, которую вы ищете: OpenEventLog . Это должно позволить вам получить доступ к удаленному журналу событий. См. Также Запрос информации о событии .

Если это не звучит правильно, я также нашел это для непосредственного разбора файлов журналов (я бы не рекомендовал такой подход, но, тем не менее, интересно):

6 голосов
/ 01 октября 2010

Читать эту статью .

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()); 
} 
1 голос
/ 14 сентября 2009

здесь миллион (и один) опций;)

Вы могли бы посмотреть на сигары

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

1 голос
/ 05 декабря 2008

Если вы хотите получить истинный доступ к журналу событий с удаленной машины, вам нужно будет найти библиотеку, которая реализует Спецификацию протокола удаленного взаимодействия EventLog . К сожалению, я еще не нашел такой библиотеки в Java. Тем не менее, большая часть основы для реализации этого протокола уже была заложена проектами JCIFS и JARAPAC. Сам протокол (если я не ошибаюсь) работает поверх протокола DCE / RPC (реализованного JARAPAC), который сам работает поверх протокола SMB (реализованного JCIFS).

Я уже использовал JCIFS и JARAPAC для реализации некоторых протоколов двоюродного брата EventLog, таких как удаленный доступ к реестру. Я могу быть слепым, но документация казалась немного скудной в отношении JARAPAC. Если вы заинтересованы в реализации этого, я могу поделиться с вами тем, что я узнал, когда у меня есть свободное время!

Позже!

...