2011-12-14 22 views
10

我想知道是否有方法從Java程序的「內部」使用Windows錯誤報告?可以將「Windows錯誤報告」用於非致命Java問題嗎?

換句話說,使用該機制將異常報告回中央位置,而不會出現實際的JVM崩潰(這是我首先理解的原因)。

這裏的想法是讓從Windows用戶收集錯誤報告更容易。


我也想聽聽它是否可以成爲受控關機的一部分。即不是JVM崩潰,而是Java程序的正常控制退出。


思前想後,我認爲,這將足以爲我們的宗旨,以創建一組文本文件(或者在一個單一的文本流只是管道)到位於我們的部分內一個微小的Windows應用程序文件系統。所述Windows應用程序然後突然崩潰並導致發送包括我們提供的文本的報告。這會起作用嗎?

+0

[NTEventLogAppender](http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/nt/NTEventLogAppender.html)或類似的東西?編輯:[可能相關的問題](http://stackoverflow.com/questions/164879/how-to-write-from-java-to-the-windows-event-log) – 2011-12-14 15:40:25

+0

@VineetReynolds,它會觸發「發送錯誤報告給微軟「行動? – 2011-12-14 15:42:40

+0

[沒有。這是配置爲僅在崩潰時發生。](http://support.microsoft.com/kb/310414) – 2011-12-14 15:44:06

回答

4

您可以與本機WER庫函數進行互操作。

下面是相關MSDN文檔:

  1. Creating a report
  2. Submitting a report

也許有人與更多的Java的互操作經驗,可以爲您提供的代碼示例,我更多的是。 NET不幸的人。

編輯:

我做了一些更多的研究,我認爲你可以嘗試使用GlueGenSWIG生成Java綁定。如果要生成綁定,您將必須download the Windows SDK才能獲得werapi頭文件。

6

我不得不在過去編寫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不會被其他應用程序使用。

10

您肯定可以使用Windows錯誤報告API作爲Win32 API的一部分在wer.dll中發貨。

從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 s - 如果它不完整或不正確,JNA網站上有tons of examplespretty good documentation

爲了運行JNA,您需要jna.jarplatform.jar,您還可以從JNA網站獲取該文件。

0

你的意思是說,而不是創建hs_err_pid * .log文件WER應該記錄日誌嗎?或者你打算記錄在WER中的Java程序中可以處理的任何異常的詳細異常消息?

如果情況是1,那麼顯然你不能做得很整齊。你可能有一個單獨的守護進程,一直運行尋找hs_err_pid * .log created->使用外部庫解釋它 - >使用上面建議的WER API將其寫入WER記錄。

如果案例是第二個,那麼你可能想要進行一個JNI調用,並調用WER API來寫入WER中的內容。