【问题标题】:Can "Windows Error Reporting" be used for non-fatal Java problems?“Windows 错误报告”可以用于非致命的 Java 问题吗?
【发布时间】:2012-01-20 09:14:58
【问题描述】:

我想知道是否有办法从 Java 程序“内部”使用 Windows 错误报告?

换句话说,使用该机制将异常报告回一个中心位置,而不会发生实际的 JVM 崩溃(据我了解,这首先是触发此问题的原因)。

这里的想法是让从 Windows 用户那里收集错误报告变得更加容易。


我也想知道它是否可以成为受控关机的一部分。 IE。不是 JVM 崩溃,而是 Java 程序的正常、受控退出。


经过深思熟虑,我认为创建一组文本文件(或者可能只是在单个文本流中通过管道传输)到位于我们文件系统部分内的一个小型 Windows 应用程序就足够了。然后,所述 Windows 应用程序显着崩溃并导致发送包含我们提供的文本的报告。这行得通吗?

【问题讨论】:

标签: java windows-error-reporting


【解决方案1】:

您的意思是说 WER 应该记录日志而不是创建 hs_err_pid*.log 文件?或者您打算记录可以在 WER 中的 Java 程序中处理的任何异常的详细异常消息?

如果 case 是 1,那么显然你不能巧妙地做到这一点。您可能一直在运行一个单独的守护进程来查找创建的 hs_err_pid*.log->使用外部库对其进行解释->使用上面建议的 WER API 将其写入 WER 记录。

如果是第二种情况,那么您可能希望进行 JNI 调用并调用 WER API 以在 WER 中编写内容。

【讨论】:

    【解决方案2】:

    您绝对可以使用 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 文档中将其拼凑起来——如果它不完整或不正确,JNA 网站上有 tons of examplespretty good documentation

    要运行 JNA,您需要 jna.jarplatform.jar,您也可以从 JNA 网站获取。

    【讨论】:

      【解决方案3】:

      过去我不得不对 Java 和 .NET 之间的互操作性进行编程,所以我开始对使用 .NET 与 WER 进行交互进行一些研究,目的是看看是否有可能与 WER 进行交互。 .NET 应用程序,然后您可以与 Java 交互。有趣的是,我在 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 似乎不适合其他应用程序使用。

      【讨论】:

      • 不确定是否有人会对此做出回应,但知道为什么该回应被否决会很有帮助 - 谢谢。
      【解决方案4】:

      您可以与本机 WER 库函数进行互操作。

      这里是相关的 MSDN 文档:

      1. Creating a report
      2. Submitting a report

      也许有更多 Java 互操作经验的人可以为您提供代码示例,不幸的是,我更像是一个 .NET 人。

      编辑:

      我做了更多研究,我认为您可以尝试使用GlueGenSWIG 来生成Java 绑定。如果要生成绑定,则必须 download the Windows SDK 获取 werapi 头文件。

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-24
      • 1970-01-01
      • 2019-03-26
      • 1970-01-01
      • 2015-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多