Can "Windows Error Reporting" be used for non-fatal Java problems?
Asked Answered
S

4

10

I was wondering if there was a way to use Windows Error Reporting from "inside" a Java program?

In other words, use the mechanism to report exceptions back to a central location without having the actual JVM crash (which to my understanding is what triggers this in the first place).

The idea here is to make it easier to collect bug reports from Windows users.


I'd like to hear too if it can be part of a controlled shutdown. I.e. not a JVM crash but a normal, controlled exit from a Java program.


After thinking it over, I think that it would be sufficient for our purposes to create a set of text files (or perhaps just pipe in a single text stream) to a tiny Windows application located inside our part of the file system. Said Windows application then crashes prominently and cause a report to be sent including the text provided by us. Would that work?

Schedule answered 14/12, 2011 at 15:32 Comment(8)
NTEventLogAppender or the like? Edit: Possibly related questionLajoie
@VineetReynolds, will it trigger the "Send bug report to Microsoft" action?Jadajadd
Nope. That is configured to occur only on a crash.Lajoie
just use log files and send them over, probably 100 lines of code and it's platform independent.Tetchy
@Tetchy does this buy the infrastructure provided by WER?Jadajadd
Windows Error Reporter deals with crashed programs, so I'm not sure how you're going to implement this. Also, this goes against the WORA ideal.Sarrusophone
Do you mean to say that instead of hs_err_pid*.log files being created WER should log the logs with it ??Vimineous
@saury it should include whatever text files we decide we want to have included from the Java application.Jadajadd
A
9

You can definitely use the Windows Error Reporting API that ships in wer.dll as part of the Win32 API.

The best way to call DLL-based functions from Java is using the actively developed Java Native Access project.

In order to make the required Win32 API calls, we'll need to teach JNA about at least these functions:

HRESULT WINAPI WerReportCreate(
  __in      PCWSTR pwzEventType,
  __in      WER_REPORT_TYPE repType,
  __in_opt  PWER_REPORT_INFORMATION pReportInformation,
  __out     HREPORT *phReportHandle
);

HRESULT WINAPI WerReportSubmit(
  __in       HREPORT hReportHandle,
  __in       WER_CONSENT consent,
  __in       DWORD dwFlags,
  __out_opt  PWER_SUBMIT_RESULT pSubmitResult
);

and also this struct:

typedef struct _WER_REPORT_INFORMATION {
  DWORD  dwSize;
  HANDLE hProcess;
  WCHAR  wzConsentKey[64];
  WCHAR  wzFriendlyEventName[128];
  WCHAR  wzApplicationName[128];
  WCHAR  wzApplicationPath[MAX_PATH];
  WCHAR  wzDescription[512];
  HWND   hwndParent;
} WER_REPORT_INFORMATION, *PWER_REPORT_INFORMATION;

To do this, we'll create WER.java:

package com.sun.jna.platform.win32;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface Wer extends StdCallLibrary {
    Wer INSTANCE = (Wer) Native.loadLibrary("wer", Wer.class,
                                                W32APIOptions.DEFAULT_OPTIONS);

    public static class HREPORT extends HANDLE {
        public HREPORT() { }
        public HREPORT(Pointer p) { super(p); }
        public HREPORT(int value) { super(new Pointer(value)); }
    }

    public static class HREPORTByReference extends ByReference {
        public HREPORTByReference() {
            this(null);
        }

        public HREPORTByReference(HREPORT h) {
            super(Pointer.SIZE);
            setValue(h);
        }

        public void setValue(HREPORT h) {
            getPointer().setPointer(0, h != null ? h.getPointer() : null);
        }

        public HREPORT getValue() {
            Pointer p = getPointer().getPointer(0);
            if (p == null)
                return null;
            if (WinBase.INVALID_HANDLE_VALUE.getPointer().equals(p)) 
                return (HKEY) WinBase.INVALID_HANDLE_VALUE;
            HREPORT h = new HREPORT();
            h.setPointer(p);
            return h;
        }
    }

    public class WER_REPORT_INFORMATION extends Structure {
        public DWORD dwSize;
        public HANDLE hProcess;
        public char[] wzConsentKey = new char[64];
        public char[] wzFriendlyEventName = new char[128];
        public char[] wzApplicationName = new char[MAX_PATH];
        public char[] wzDescription = new char[512];
        public HWND hwndParent;

        dwSize = new DWORD(size());
    }

    public abstract class WER_REPORT_TYPE {
        public static final int WerReportNonCritical = 0;
        public static final int WerReportCritical = 1;
        public static final int WerReportApplicationCrash = 2;
        public static final int WerReportApplicationHang = 3;
        public static final int WerReportKernel = 4;
        public static final int WerReportInvalid = 5;
    }

    HRESULT WerReportCreate(String pwzEventType, int repType, WER_REPORT_INFORMATION pReportInformation, HREPORTByReference phReportHandle);
    HRESULT WerReportSubmit(HREPORT hReportHandle, int consent, DWORD dwFlags, WER_SUBMIT_RESULT.ByReference pSubmitResult);
}

I just knocked that together from the MSDN dcoumentation in a few minutes--in case it's incomplete, or incorrect, there are tons of examples and pretty good documentation on the JNA web site.

In order to run JNA, you'll need jna.jar and platform.jar, which you can also grab from the JNA web site.

Algernon answered 28/12, 2011 at 23:34 Comment(0)
F
6

I've had to program inter-operability between Java and .NET in the past, so I started to do some research on using .NET to interact with WER with the intention to see if it's possible to interact with WER in a .NET app that you could then interface with Java. Interestingly, I came across this post on SOF - Is there a .Net API for Windows Error Reporting

That post has some good information related to interacting with WER.

I know that the post revolves around using .NET against WER, but as you're trying to interact with native Windows functionality, I recommend using .NET to interact with it as it's SO much easier to interact with native Windows resources using .NET than it is with Java (and it usually takes half the code it would in Java). You could then interface to the .NET app (might be best set up as a Windows service) with Java (for instance, you could use temporary "trigger" files in the .NET app to indicate when the .NET app is done with it's processing; the Java app could then probe to see when that "trigger" file has been created and continue from there...).

As the accepted answer in that post recommends, though, it might be best to use Windows Quality Online Services instead of programming something to interact with WER as it appears that WER is not meant to be used by other applications.

Florentinaflorentine answered 22/12, 2011 at 16:33 Comment(1)
Not sure if anyone will ever respond to this, but it would be helpful to know why this response was downvoted - thanks.Florentinaflorentine
S
4

You could interop with the native WER library functions.

Here is the relevant MSDN documentation:

  1. Creating a report
  2. Submitting a report

Perhaps someone with more Java-interop experience can provide you with code examples, I'm more of a .NET guy unfortunately.

EDIT:

I did some more research, and I think you could try using GlueGen or SWIG to generate the Java bindings. You will have to download the Windows SDK to get the werapi header file if you want to generate the bindings.

Speaker answered 22/12, 2011 at 11:30 Comment(1)
You can do the work in a Thread-wide UncaughtExceptionHandler if you want: docs.oracle.com/javase/1.5.0/docs/api/java/lang/…. But this is probably not a good practice.Speaker
V
0

Do you mean to say that instead of hs_err_pid*.log files being created WER should log the logs with it ??Or you intent to log the detailed exception message of any exception which can be handled in Java programs in WER ?

If the case is 1 then obviously you can't do it neatly. You may have a separate daemon running all the time to look for hs_err_pid*.log created->interpret it using external libraries->use WER APIs suggested above to write it in WER recorords.

If the case is 2nd one then you may like to make a JNI call and have the calls made to WER APIs to write stuff in WER.

Vimineous answered 29/12, 2011 at 4:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.