2014-08-30 45 views
1

昨天在這裏由q提示,我試圖重新熟悉TGeckoBrowser 從這裏:http://sourceforge.net/p/d-gecko/wiki/Home如何避免在德爾福應用程序中使用TGeckoBrowser的異常

(注:需要安裝了Mozilla的XULRunner包)

事情似乎已經向後移動了一下,因爲我最後一次試圖在WinXP的時代,在 以最少的D7項目導航到一個URL ,我收到錯誤,我不記得以前看過 。我已經在下面包含了我的代碼。這些錯誤是我跑到 導航到www.google.com,news.bbc.co.uk等網站,當然還有這裏。

  1. 第一個例外 - 「Safecall方法中的例外」 - 在我的表單首次顯示之前發生,隨後在任何地方進行導航。我有一個TApplication.OnException處理程序的形式。

我的問題是:a)有沒有人知道如何避免它,或者b)有沒有比建立一個TApplication.Exception處理程序更加整潔的方式,它總是讓我感覺像是一個位 一個失敗的承認(我的意思是有一個避免用戶看到一個異常,根本沒有一個應用程序範圍的處理程序)。

這個例外在此代碼中出現:

procedure TCustomGeckoBrowser.Paint; 
var 
    rc: TRect; 
    baseWin: nsIBaseWindow; 
begin 
    if csDesigning in ComponentState then 
    begin 
    rc := ClientRect; 
    Canvas.FillRect(rc); 
    end else 
    begin 
    baseWin := FWebBrowser as nsIBaseWindow; 
    baseWin.Repaint(True); 
    end; 
    inherited; 
end; 
在調用baseWin.Repaint

,所以大概是 大概是從界面的另一邊來了。我只知道它第一個 時間.Paint被調用。我注意到那時,baseWin返回False GetVisibility, 因此在我的TForm1.Loaded實驗代碼,看看是否會避免它。 它沒有。

2.a調用GeckoBrowser1.LoadURI後,根據加載的URL,我得到「無效的浮點運算」 一次或多次。

2.b再一次,根據URL,我得到:「模塊js3250.dll中的地址556318B3上的訪問衝突。地址00000008的讀取。」或類似的。在一些頁面上,它每隔幾秒就會發生一次(謝謝我想象一下頁面中的一些JS計時器代碼)。

2A & 2B通過調用避免在下面TForm1.OnCreate Set8087CW但我 提他們主要萬一有人認識他們,某種形式的系統性問題的1一起對症 ,也讓谷歌對於遇到這些症狀的其他人會發現這個問題。

恢復到我的q 1b),在StdWndProc-> TWinControl.MainWndProc - > [...] - > TCustomGeckoBrowser.Paint中出現「Safecall方法中的異常」。而不是使用一個 TApplication.OnException處理程序,有沒有辦法在調用鏈上捕獲異常進一步 ,以避免修改TCustomGeckoBrowser.Paint的代碼 在那裏放置一個處理程序?

更新:註釋吸引了我的注意有關SafeCall本文檔:當safecall錯誤處理程序尚未建立和safecall例行返回一個非0的HResult,或

ESafecallException上升如果safecall錯誤處理程序不引發異常。如果發生此異常,Comobj單元可能從應用程序的使用列表(Delphi)中丟失或未包含在項目源文件(C++)中。您可能需要考慮從導致異常的例程中移除safecall調用約定。

GeckoBrowser源代碼提供了一個單元BrowserSupports,它看起來像一個類型庫導入單元,除了它似乎已經手動準備。它包含一個接口,其中包含正在生成SafeCall異常的Repaint方法。

nsIBaseWindow = interface(nsISupports) 
    ['{046bc8a0-8015-11d3-af70-00a024ffc08c}'] 
    procedure InitWindow(parentNativeWindow: nativeWindow; parentWidget: nsIWidget; x: PRInt32; y: PRInt32; cx: PRInt32; cy: PRInt32); safecall; 
    procedure Create(); safecall; 
    procedure Destroy(); safecall; 
    [...] 
    procedure Repaint(force: PRBool); safecall; 
    [...] 
    end; 

繼quoyed文檔中的建議,我改個「safecall」以STDCALL重繪件(但只有成員)和,急!異常停止發生。如果它在接下來的幾天內不會再出現,我會將其作爲答案發布,除非有人提出了更好的答案。

我的項目代碼:

uses 
    BrowserSupports; 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    Set8087CW($133F); 
    Application.OnException := HandleException; 
end; 

procedure TForm1.HandleException(Sender: TObject; E: Exception); 
begin 
    Inc(Errors); 
    Caption := Format('Errors %d, msg: %s', [Errors, E.Message]); 
    Screen.Cursor := crDefault; 
end; 

type 
    TMyGeckoBrowser = class(TGeckoBrowser); 

procedure TForm1.Loaded; 
begin 
    inherited; 
    GeckoBrowser1.HandleNeeded; 
(TMyGeckoBrowser(GeckoBrowser1).WebBrowser as nsIBaseWindow).SetVisibility(True); 
end; 

procedure TForm1.btnLoadUrlClick(Sender: TObject); 
begin 
    try 
    GeckoBrowser1.LoadURI(edUrl.Text); 
    except 
    end; 
end; 
+0

Safecall異常包裝HRESULT。它是什麼? – 2014-08-30 12:53:36

+0

我不確定如何獲得HRESULT值。在CPU窗口中,Repaint做了一個「call dword ptr [eax + $ 30]」,接下來的一行是「call @CheckAutoResult」 - 跟蹤第一個導致不可見的彙編程序。然而,在調用CheckAutoResult時,EAX是8004005(5的低字節通常不意味着「訪問被拒絕」,iirrc?),其中CheckAutoResult變成80004018,其中018大概是我在早期的eval窗口,是「Safecall方法中的例外」。很抱歉,如果這不回答您的查詢。 – MartynA 2014-08-30 13:55:59

+0

引發了什麼異常類 – 2014-08-30 14:00:01

回答

0

望着頭,原型爲Repaint是有效如下:

HRESULT __stdcall Repaint(PRBool force); 

,這意味着,

procedure Repaint(force: PRBool); safecall; 

是合理的宣言。請記住safecall執行參數重寫將COM錯誤代碼轉換爲異常。

這確實意味着如果對Repaint的調用返回一個表示失敗的值,那麼safecall機制將表現爲異常。如果你想忽略這個特殊的例外,那麼它是清潔,從源頭這樣做:

try 
    baseWin.Repaint(True); 
except 
    on EOleException do 
    ; // ignore 
end; 

如果你想避免處理異常,那麼你可以切換到stdcall,但你必須記住撤消參數重新寫作。

function Repaint(force: PRBool): HRESULT; stdcall; 

現在你可以寫這樣的:

if Failed(baseWin.Repaint(True)) then 
    ; // handle the error if you really wish to, or just ignore it 

注意FailedActiveX單元定義。

如果你想解決錯誤進一步,那麼你可以看看錯誤代碼:

var 
    hres: HRESULT; 
.... 
hres := baseWin.Repaint(True); 
// examine hres 

或者,如果你要離開的功能safecall然後你可以檢索從EOleException實例的錯誤代碼ErrorCode財產。

+0

謝謝。當然,我希望做的是找到一種處理問題的方法,或者首先避免它,而不涉及TGeckoBrowser源。幾天的測試讓我相當確信這個錯誤只會在第一次調用Repaint()時發生,所以它很可能是接口的一端或另一端的初始化問題。就目前情況而言,直接從調色板出來的TGeckoBrowser在第一次嘗試出現在r/t時失敗。我會減少我的注意力。 – MartynA 2014-09-02 13:20:37

+0

我不知道a)在你的Q中,但我認爲我處理了b) – 2014-09-02 13:21:58