1

I am solving this issue:

In my Java application (installed on Windows OS machine) I have to catch Win32 Event which is created by another application on same machine. This app is written in C++ and there is no way to change it. I have information that I have to use OpenEvent function. I started as is metioned in: Calling OpenEvent fails through JNA

Here is my code:

    public class WinEventListener {
    private Logger logger = LoggerFactory.getLogger(WinEventListener.class);

    static {
        Native.register("kernel32");
    }

    public static native HANDLE OpenEventW(int access, boolean inheritHandle, WString name);

    public static native int WaitForSingleObject(HANDLE hHandle, int dwMilliseconds);

    public static native boolean CloseHandle(HANDLE hObject);

    public static class HANDLE extends PointerType {

        public Object fromNative(Object nativeValue, FromNativeContext context) {
            Object o = super.fromNative(nativeValue, context);
            if (INVALID_HANDLE_VALUE.equals(o))
                return INVALID_HANDLE_VALUE;
            return o;
        }
    }

    static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {

        {
            super.setPointer(Pointer.createConstant(-1));
        }

        public void setPointer(Pointer p) {
            throw new UnsupportedOperationException("Immutable reference");
        }
    };

    public void listen() throws Exception {
        HANDLE handle = null;
        do {
            //logger.debug("Wainting for handle");
            handle = OpenEventW(2, false, new WString("VLIT_SERVER_DATA"));
            logger.debug("Handle:" + handle.toString());
            Thread.sleep(1000);
        } while (handle == null);
        logger.debug("Handle obtained");

        while(true){
            int result = WaitForSingleObject(handle,Integer.MAX_VALUE);
            if(result == 0){
                logger.debug("Handle signalized");
                VLITProcceserThread thread = new VLITProcceserThread();
                thread.start();
                CloseHandle(handle);
            }
        }

    }


}

Basiclly I want in listen() method wait for HANDLE create by other program and if its created then wait for its signalized state, do some action and release handle.

BUt I have no success. Can anybody point me to right way?

Thans a lot!

Community
  • 1
  • 1
  • 1
    What does "no success" mean? Where does the code fail? What does `OpenEventW` return? If any APIs fail, how do they fail? I cannot see any calls to `GetLastError`. – David Heffernan May 14 '14 at 12:21
  • Hi, i am sorry that i am writting after long period. I have modified code and added GetLastError like this: public static native int GetLastError(); and i am calling it after each attempt to get handle: handle = OpenEventW(2, false, new WString("VLIT_SERVER_DATA")); logger.debug("After open event:"+GetLastError()); This call always returns 0 so that there no failure as i found at documentation. Neverthless hanle is still null. Is it possible that there is no such event in OS yet? The authors of C++ app are sayng that there should be... – Berťas Dostál May 21 '14 at 08:10
  • Only call `GetLastError` if the docs tell you to. Typically that is only if the function call fails. For instance, `OpenEvent` returns `NULL` to indicate failure. Only then call `GetLastError`. But you have to read the docs for each and every API function because error handling varies. – David Heffernan May 21 '14 at 08:12
  • GetLastError returns 0. OpenEventW returns NULL. There should be not 0 value after calling OpenEventW in GetLastError if there is any error am I right? And please what is difference between OpenEventW and OpenEvent functions? I cannot find it out on docs. – Berťas Dostál May 21 '14 at 08:18
  • Is there possibility that i use wrong String value? Should it be WString? And shoudl it be explicitly encoded to UNICODE? – Berťas Dostál May 21 '14 at 08:36
  • `WString` is right I believe. Calling `GetLastError` directly is problematic. Sorry, I should have realised. The framework (Java runtime, JNA etc.) will call Win32 API functions in between the actual call returning, and your call to `GetLastError`. Thus the error code is lost. This question has more info: http://stackoverflow.com/questions/8413963/how-to-make-getlasterror-reliably-work-with-jna You will need to follow the advice in the answer there, which just happens to be mine! – David Heffernan May 21 '14 at 09:45
  • Hello, approach mentioned in http://stackoverflow.com/questions/8413963/how-to-make-getlasterror-reliably-work-with-jna helped. Now Native.GetLastError returns number 2 which means ERROR_FILE_NOT_FOUND. Can it be due to there is still no event in system or am I using wrong permissions in OpenEventW function? – Berťas Dostál Jun 03 '14 at 11:40
  • That means that there is no event with that name. – David Heffernan Jun 03 '14 at 11:42
  • Thank you very much for your advices. Could you suggest me some good link or example to write same program in C/C++? To be sure this is not Java/JNA issue. I have searched inet but could not find suitable one. – Berťas Dostál Jun 04 '14 at 11:36
  • It could not really be easier. Assuming you have Visual Studio, create a new C++ console app. Include `` and then write `HANDLE handle = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"VLIT_SERVER_DATA");` Then check what value `handle` has. Realistically I suspect that you will need to use a kernel object viewer to work out how to find this event's name. – David Heffernan Jun 04 '14 at 11:39
  • So after communication with authors of C++ app I have found out that they give me wrong event name... it should be Global\\VLIT_SERVER_DATA. Now I am getting error code 5: permission denied:( I use sync level. Please dont you know if there should be any right to Windows user I am currently logged in to be able to read event in Globa\\ namaspace? Thank you. – Berťas Dostál Jun 18 '14 at 07:51
  • You'll need admin rights to use an object in the global namespace – David Heffernan Jun 18 '14 at 07:53

1 Answers1

0

If it is the opening of the handle that is failing it is most likely an issue with privileges. Is your program running as a service? I was trying to do something similar and was able to get this program running and working when i called it via a system call inside a program that was running as a service.

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.WString;
import com.sun.jna.FromNativeContext;

public class WinEventListener {
    static {
        Native.register("kernel32");
    }

public static native HANDLE OpenEventW(int access, boolean inheritHandle, WString name);

public static native int WaitForSingleObject(HANDLE hHandle, int dwMilliseconds);

public static native boolean CloseHandle(HANDLE hObject);

public static class HANDLE extends PointerType {

    public Object fromNative(Object nativeValue, FromNativeContext context) {
        Object o = super.fromNative(nativeValue, context);
        if (INVALID_HANDLE_VALUE.equals(o))
            return INVALID_HANDLE_VALUE;
        return o;
    }
}

static HANDLE INVALID_HANDLE_VALUE = new HANDLE() {

    {
        super.setPointer(Pointer.createConstant(-1));
    }

    public void setPointer(Pointer p) {
        throw new UnsupportedOperationException("Immutable reference");
    }
};

public void listen() {
    try {


        HANDLE handle = null;
        do {
            handle = OpenEventW(2031619, false, new WString("event_name"));
            if(handle == null) {
                System.out.print("Handle is null\n");
            }
            Thread.sleep(500);
        } while (handle == null);

        while(true){
            // 50 second timeout
            int result = WaitForSingleObject(handle, 50000);
            if(result == 0){
                System.out.print("Handle signaled\n");
            }
            else if (result == 258){
                System.out.print("Timed out\n");
            }
            else{
                System.out.print("Handle not signaled\n");
                System.out.print(result);
            }
            System.out.print(result);
            //System.out.print(handle);
            Thread.sleep(100);
        }
    }
    catch (Exception exc)
    {
        System.out.print(exc);
        //Thread.sleep(10000);

        //writer.writeln(exc);
    }

}

public static void main(String[] args) {
    WinEventListener listener = new WinEventListener();
    listener.listen();
}

}