2014-01-31 26 views
10

我正在嘗試add an additional button into a toolbar in Internet Explorer爲什麼我的TB_INSERTBUTTON消息導致comctl32拋出?

我認爲,實現的直線前進,而現在使用此代碼:

TBBUTTON buttonToAdd; 
ZeroMemory(&buttonToAdd, sizeof(TBBUTTON)); 
buttonToAdd.iBitmap = 1; 
buttonToAdd.idCommand = 1; 
buttonToAdd.fsState = TBSTATE_ENABLED; 
buttonToAdd.fsStyle = BTNS_BUTTON|BTNS_AUTOSIZE; 

LRESULT insertButtonResult = SendMessage(hWndToolbar, TB_INSERTBUTTON, 0, (LPARAM)&buttonToAdd); 

當發送消息時,Internet Explorer將崩潰90%的時間(10%的時候,我獲取工具欄上有點破損按鈕),但下列情況除外:

Unhandled exception at 0x000007FEFB97DDFA (comctl32.dll) in iexplore.exe: 0xC000041D: An unhandled exception was encountered during a user callback.

考慮的R結果不一致,我假設了某種內存佈局問題。所以我試圖發送TB_INSERTBUTTONA而不是(我的應用程序默認爲TB_INSERTBUTTONW),但是這對問題沒有影響。

我也試過我的應用程序的32和64版本,都有相同的結果。

我看了看在iexplore.exe調用堆棧,它看起來像這樣:

comctl32.dll!CToolbar::TBInputStruct(struct _TBBUTTONDATA *,struct _TBBUTTON const *) Unknown 
comctl32.dll!CToolbar::TBInsertButtons(unsigned int,unsigned int,struct _TBBUTTON *,int) Unknown 
comctl32.dll!CToolbar::ToolbarWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown 
comctl32.dll!CToolbar::s_ToolbarWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown 
user32.dll!UserCallWinProcCheckWow() Unknown 
user32.dll!DispatchClientMessage() Unknown 
user32.dll!__fnDWORD() Unknown 
ntdll.dll!KiUserCallbackDispatcherContinue() Unknown 
user32.dll!NtUserPeekMessage() Unknown 
user32.dll!PeekMessageW() Unknown 
... 

我發現有些有趣,因爲我假設在上面拷貝數據的方法,從我的輸入結構成內部結構和一些錯誤。但是我的輸入數據結構有什麼問題?

源代碼本身可以在GitHub上的:https://github.com/oliversalzburg/ie-button

+0

備註 - 這是嘗試打開黑盒Microsoft技術的一部分,以便任何人都可以輕鬆地免費創建IE擴展,而不必使用閉源專有技術。 –

+6

請注意,IE可能決定在將來更改工具欄技術,或者它可能會更改其窗口層次結構,因此工具欄位於不同的位置。 (這兩種情況都發生在過去。)這段代碼依賴於IE的無證行爲,並且需要明確說明您的程序依賴於它,以便您的客戶知道他們在做什麼。 –

+0

@RaymondChen你當然是對的。這是在SE的另一個問題上的開放技術努力,我們一次只能計算出一個IE版本(IE9-IE11可能是一個非常好的開始)。人們開發在IE上運行的擴展非常困難,這一事實令人驚訝。 –

回答

7

這是失敗,因爲您要發送包含跨進程邊界指針的消息。請注意,你傳遞一個地址的事實:

LRESULT insertButtonResult = SendMessage(hWndToolbar, TB_INSERTBUTTON, 0, 
    (LPARAM)&buttonToAdd); 

這最後一個參數是在你的進程地址的地址空間。但收件人是一個不同的過程,並且您傳遞的地址在另一個過程的地址空間中沒有意義。

某些消息(例如WM_SETTEXT)將由系統將其有效負載編組到其他進程。但TB_INSERTBUTTON不屬於該類別。 TB_INSERTBUTTON的規則之一是您傳遞的指針在擁有收件人窗口的過程中有意義。

您可以通過使用VirtualAlloc,WriteProcessMemory等來分配和寫入該另一個進程中的內存來解決此問題。

被警告,這是一個有點困難的任務得到正確的。特別是這兩個進程是否具有相同的位數很重要。結構的佈局在32位和64位之間不同。確保發送正確佈局的最簡單方法是以與目標進程相同的位數編譯進程。

到目前爲止,做這種事最簡單的方法是在目標進程中。如果你要編寫一個插件,那麼你將不必處理任何這些問題,並且也能夠使用官方支持的API進行擴展。

正如雷蒙德所說,你試圖做的事情是相當危險的,你最好聽從他的建議。

+0

與此相關的主要問題是,IE允許通過在單獨進程上運行的BHO(瀏覽器幫助程序對象)進行擴展。 Propyatory框架完成了這一任務 - 但對於想要構建開源跨瀏覽器擴展的外行開發人員來說,這是非常困難的。 –

+0

我聽到你響亮而清晰。我並不特別喜歡以非標準的方式修改應用程序UI。但我認爲這是一個有趣的挑戰。那謝謝啦 :) –

相關問題