我想知道是否有一种方法可以使用Windows错误报告从"内部"的Java程序?
换句话说,使用该机制将异常报告回中央位置,而不会导致实际的JVM崩溃(根据我的理解,JVM崩溃是首先触发异常的原因)。
这里的想法是让收集Windows用户的bug报告变得更容易。
我也想知道它是否可以作为受控关闭的一部分。也就是说,不是JVM崩溃,而是正常的、受控的退出Java程序。
在仔细考虑之后,我认为创建一组文本文件(或者只是在单个文本流中管道)到位于我们文件系统内的一个小Windows应用程序就足够了。该Windows应用程序随后明显崩溃,并导致发送报告,其中包括我们提供的文本。这样行吗?
你绝对可以使用wer.dll
附带的Windows错误报告API作为Win32 API的一部分。
从Java调用基于dll的函数的最好方法是使用积极开发的Java Native Access项目。
为了进行所需的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文档中拼凑了这些-如果它不完整或不正确,在JNA网站上有大量的示例和相当好的文档。
为了运行JNA,你需要jna.jar
和platform.jar
,你也可以从JNA网站上获取。
过去我必须编写Java和。net之间的互操作性,所以我开始做一些关于使用。net与WER交互的研究,目的是看看是否有可能在一个可以与Java交互的。net应用程序中与WER交互。有趣的是,我在soff上看到了这篇文章——是否有一个。net API用于Windows错误报告
那篇文章有一些关于与WER交互的好信息。
我知道这篇文章围绕着使用。net来对抗WER,但是当你试图与本机Windows功能交互时,我建议使用。net来与它交互,因为使用。net与本机Windows资源交互比使用Java要容易得多(它通常只需要Java一半的代码)。然后你可以用Java连接。net应用程序(可能最好设置为Windows服务)(例如,你可以在。net应用程序中使用临时"触发器"文件来指示。net应用程序何时完成处理;然后,Java应用程序可以探测是否创建了"触发器"文件,并从那里继续…)。
正如那篇文章中公认的答案所建议的那样,尽管如此,最好使用Windows质量在线服务,而不是编程一些东西来与WER交互,因为WER似乎不打算被其他应用程序使用。
您可以与本地的WER库函数进行互操作。
以下是相关的MSDN文档:
- 创建报告
- 提交报告
也许有更有java互操作经验的人可以为你提供代码示例,不幸的是,我更喜欢。net。
编辑:我做了更多的研究,我认为你可以尝试使用GlueGen或SWIG来生成Java绑定。如果你想生成绑定,你必须下载Windows SDK来获取werapi头文件。
你的意思是说,而不是hs_err_pid*.log文件被创建的WER应该用它记录日志吗?或者您打算在WER中记录任何可以在Java程序中处理的异常的详细异常消息?
如果情况是1,那么显然你不能做得很整齐。您可能一直运行一个单独的守护进程来查找创建的hs_err_pid*.log ->使用外部库解释它->使用上面建议的WER api将其写入WER记录。
如果是第二种情况,那么你可能喜欢进行JNI调用,并调用WER api来在WER中编写内容。