简体   繁体   English

如何使用Java注册WMI事件

[英]How to register for WMI events using Java

I am integrating window based application with java application and want to capture window events in java. 我正在将基于窗口的应用程序与Java应用程序集成在一起,并希望捕获Java中的窗口事件。

I found in google J-Interop is the library thorugh this can be achived. 我在Google J-Interop中找到的是可以实现的库。 i did some POC wih below code but facing issue while locating the service ie WbemScripting.SWbemLocator 我在代码下面做了一些POC wih,但是在定位服务即WbemScripting.SWbemLocator时遇到了问题

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 String domainName = "domain";
private static String userName="user";
private static String password="psswd";
private static String hostIP ="127.0.0.1";
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
{
    //HKEY_CLASSES_ROOT\CLSID\{76A64158-CB41-11D1-8B02-00600806D9B6}
    //WbemScripting.SWbemLocator
    JIComServer wbemLocatorComObj = new JIComServer( JIProgId.valueOf( "76A64158-CB41-11D1-8B02-00600806D9B6" ), host, dcomSession );
    System.out.println("com objected created");
    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 )
{



    String domain = domainName;//args[ 0 ];
    String host = hostIP;//args[ 1 ];
    String user = userName;//args[ 2 ];
    String pass = password;//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.
        System.out.println("listner statred");
        while ( true )
        {
            System.out.println("vinod");
            // 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();
            }
        }
    }
}

}

Error: 错误:

org.jinterop.dcom.common.JIException: The system cannot find the file specified. Please check the path provided as parameter. If this exception is being thrown from the WinReg package, please check if the library is registered properly or do so using regsvr32. [0x00000002]
    at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenKey(JIWinRegStub.java:195)
    at org.jinterop.dcom.core.JIProgId.getIdFromWinReg(JIProgId.java:129)
    at org.jinterop.dcom.core.JIProgId.getCorrespondingCLSID(JIProgId.java:160)
    at org.jinterop.dcom.core.JIComServer.<init>(JIComServer.java:428)
    at com.stg.commons.behave.reporting.EventLogListener.getWmiLocator(EventLogListener.java:49)
    at com.stg.commons.behave.reporting.EventLogListener.main(EventLogListener.java:81)
Caused by: org.jinterop.dcom.common.JIRuntimeException: The system cannot find the file specified. Please check the path provided as parameter. If this exception is being thrown from the WinReg package, please check if the library is registered properly or do so using regsvr32. [0x00000002]
    at org.jinterop.winreg.IJIWinReg$openKey.read(IJIWinReg.java:938)
    at ndr.NdrObject.decode(NdrObject.java:36)
    at rpc.ConnectionOrientedEndpoint.call(ConnectionOrientedEndpoint.java:137)
    at rpc.Stub.call(Stub.java:113)
    at org.jinterop.winreg.smb.JIWinRegStub.winreg_OpenKey(JIWinRegStub.java:189)
    ... 5 more

This is the clue: 这是线索:

"If this exception is being thrown from the WinReg package, please check if the library is registered properly or do so using regsvr32." “如果从WinReg软件包中抛出此异常,请检查该库是否已正确注册,或使用regsvr32进行注册。”

It seems the necessary library of your Windows application is not properly registered yet. 似乎您的Windows应用程序的必需库尚未正确注册。 From the command prompt (in admin mode), you can use regsvr32 to do that: 在命令提示符下(以管理员模式),您可以使用regsvr32来执行此操作:

regsvr32 yourlib.dll

References: 参考文献:

  • There is a similar thread here 有一个类似的线程在这里
  • How to register a DLL using regsvr32 can be found here 如何在这里找到使用regsvr32注册DLL的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM