I have an app in Delphi XE2 (runs on Win7 x64, MSIE 10.0.9200.16635 installed), which creates multiple threads. Each thread creates IWebBrowser2 interface, which then navigates to a web page, saves it to disk, deletes IWebBrowser2 interface and terminates thread. "Silent" property of the web browser is set to true. The problem is that with certain URLs I get these errors AFTER terminating a working thread (e.g. web browser should not exist anymore: Screenshot1 Screenshot2
These are JavaScript errors, the first one says "Function expected", URL res://ieframe.dll/preview.js, and the other one is "The callee (server [not server application]) is not available and disappeared; all connecitons are invalid. The call did not execute". The URL is the same, res://ieframe.dll/preview.js. All I need is to supress these error dialogs, but I can't. IWebBrowser2 does not have "ScriptErrorsSuppressed" property, so I can't go this way. Sometimes I get the first message and sometimes the other one. I have spent three days looking for answer and I am helpless. Working threads do their job, I have no memory leaks - the only problem is these error dialogs. I have disabled debugging and error messages in MSIE's advanced options, but it does not help. What I think can be happening here is that after thread and all objects are "officially" deleted, the javascript from the page is still being executed somewhere in memory. Then, it discovers that browser object is gone and that's why I am probably getting this second message "The callee (server...".
Here is my code:
function AtlAxAttachControl(const pControl: IUnknown;
hWnd: HWND; ppUnkContainer: IUnknown): DWORD; stdcall; external 'ATL.DLL';
procedure TWPThread.Execute;
const
CLSID_InternetExplorer: TGUID = '{8856F961-340A-11D0-A96B-00C04FD705A2}';
var
WndClass: TWndClassEx;
WebBrowser: IWebBrowser2;
Handle: HWND;
Msg:TMsg;
iall:IHTMLElement;
begin
FillChar(WndClass, SizeOf(WndClass), 0);
with WndClass do
begin
cbSize := SizeOf(WndClass);
lpszClassName := 'MESSAGE_ONLY_WINDOW';
lpfnWndProc := @DefWindowProc;
end;
RegisterClassEx(WndClass);
Handle := CreateWindowEx(0, WndClass.lpszClassName, nil, 0, 0, 0, 0, 0, DWORD(HWND_MESSAGE), 0, 0, nil);
if (Handle = 0) then raise Exception.Create('CreateWindowEx');
try
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
if (CoCreateInstance(CLSID_InternetExplorer, nil, CLSCTX_INPROC_SERVER, IID_IWebBrowser2, WebBrowser) <> S_OK) then raise Exception.Create('CoCreateInstance');
try
AtlAxAttachControl(WebBrowser, Handle, nil);
WebBrowser.Silent:=True;
WebBrowser.Navigate('http://investing.money.msn.com/investments/stock-report?CR=1&AF=1&IH=1&AIE=1&AIR=1&FRH=1&FRK=1&ISA=1&ISQ=1&BSA=1&BSQ=1&CFA=1&CFQ=1&TYS=1&ITT=1&ITP=1&Type=Equity&Symbol=AAN', EmptyParam, EmptyParam, EmptyParam, EmptyParam) ;
while (WebBrowser.ReadyState <> READYSTATE_COMPLETE) do
begin
while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do DispatchMessage(Msg);
Sleep(1);
end;
// MessageBoxW(0, PWideChar((wb.Document as IHTMLDocument2).title), '', 0);
iall := (WebBrowser.Document AS IHTMLDocument2).body;
while iall.parentElement <> nil do iall := iall.parentElement;
Form1.Memo1.Text := iall.outerHTML;
Form1.Memo1.Lines.SaveToFile('D:\memo.html');
finally
WebBrowser:=Nil;
end;
finally
DestroyWindow(Handle);
CoUninitialize;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
TWPThread.Create;
end;
What am I doing wrong? Is there a method that can prevent appearing these error dialogs? I was thinking about injecting my own JavaScript in the downloaded page - e.g. my own window.onerror handler which would supress error, but I am not sure if it is a correct way, and also I am not good with JavaScript, especially with this code injecting stuff.
Any help greatly appreciated, thank you! Ace.