我想知道是否有办法从Java程序的“内部”使用Windows错误报告?
换句话说,使用该机制将异常报告回中心位置而不会导致实际的JVM崩溃(据我所知,这首先触发了这一点)。
这里的想法是更容易从Windows用户收集错误报告。
我也想听听它是否可以成为受控关机的一部分。即不是JVM崩溃,而是从Java程序正常,受控制的退出。
在考虑完之后,我认为为我们的目的创建一组文本文件(或者可能只是在单个文本流中管道)到位于我们文件系统内部的小型Windows应用程序就足够了。然后,所述Windows应用程序突然崩溃并导致发送报告,包括我们提供的文本。那会有用吗?
答案 0 :(得分:9)
您绝对可以使用wer.dll
中附带的Windows错误报告API作为Win32 API的一部分。
从Java调用基于DLL的函数的最佳方法是使用积极开发的Java Native Access project。
为了进行必要的Win32 API调用,我们需要向JNA讲授至少这些函数:
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
);
以及这个结构:
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;
为此,我们将创建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);
}
我只是在几分钟内从MSDN dcoumentation中一起敲了 - 如果它不完整或不正确,JNA网站上有tons of examples和pretty good documentation。
要运行JNA,您需要jna.jar
和platform.jar
,您也可以从JNA网站上获取。
答案 1 :(得分:6)
过去我必须编写Java和.NET之间的互操作性,因此我开始研究如何使用.NET与WER进行交互,以便了解是否可以在WER中与WER进行交互。然后可以与Java交互的.NET应用程序。有趣的是,我在SOF上发现了这篇文章 - Is there a .Net API for Windows Error Reporting
该帖子提供了与WER交互相关的一些好信息。
我知道这篇文章围绕着使用.NET来对抗WER,但是当你尝试与本机Windows功能进行交互时,我建议使用.NET与它进行交互,因为使用本机Windows资源进行交互更加容易。 .NET比使用Java(它通常占用Java的一半代码)。然后,您可以使用Java与.NET应用程序(可能最好设置为Windows服务)连接(例如,您可以在.NET应用程序中使用临时“触发器”文件来指示.NET应用程序何时完成它处理; Java应用程序然后可以探测以查看何时创建了“触发器”文件并从那里继续......)。
正如该帖子中所接受的答案所建议的那样,最好使用Windows Quality Online Services而不是编写与WER交互的内容,因为看起来WER并不打算被其他应用程序使用。
答案 2 :(得分:4)
您可以与原生WER库函数互操作。
以下是相关的MSDN文档:
也许拥有更多Java-interop经验的人可以为您提供代码示例,不幸的是,我更像是一个.NET人员。
修改强>
我做了更多的研究,我认为您可以尝试使用GlueGen或SWIG来生成Java绑定。如果要生成绑定,则必须download the Windows SDK才能获取werapi头文件。
答案 3 :(得分:0)
你的意思是说,而不是创建hs_err_pid * .log文件WER应该用它记录日志吗?或者你打算记录任何可以在WER中的Java程序中处理的异常的详细异常消息?
如果案件是1那么显然你不能整齐地做到这一点。您可能有一个单独的守护程序一直在运行以查找hs_err_pid * .log created->使用外部库解释它 - >使用上面建议的WER API将其写入WER记录中。
如果案例是第二个案例,那么您可能希望进行JNI调用,并调用WER API来编写WER中的内容。