1

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.

Acetylator
  • 19
  • 2
  • 1
    not really an anser but you can stop hurting your self and use TEmbeddedWB from http://bsalsa.com, or take look at the source code and realize it's not that simple... – whosrdaddy Jul 11 '13 at 08:05
  • 1
    If you only want to get page contents and save it to disk, why don't you instead use Indy's `TIdHTTP` component? – LightBulb Jul 11 '13 at 08:05
  • What LightBulb says. Your entire approach is wrong. Use the right approach and this problem does not exist. – David Heffernan Jul 11 '13 at 08:11
  • 1
    LightBulb, I must use MSIE engine to download pages where I need JavaScript to run (they are dynamically generated). In cases where content is static I don't use IWebBrowser2, I use ICS from F.Piette (something linke Indy). The main problem that I am trying to solve here is not just saving a webpage to disk, but saving a dynamically generated web page to disk, probably I should have noted it in advance. – Acetylator Jul 11 '13 at 08:18
  • Whorsdaddy, thanks for info about TEmbeddedWB, I probably give it a try in case it is thread-safe. – Acetylator Jul 11 '13 at 08:19
  • UPDATE: So, I tried using TEmbeddedWB. Creating object of this type in Thread.Execute causes applicaiton crash. So, I suppose it is not thread-safe or I am doing something wrong... – Acetylator Jul 11 '13 at 10:04
  • I think this is what you are looking for: http://stackoverflow.com/a/2937871/800214. I am going to vote to close this question as it is in fact a duplicate. – whosrdaddy Jul 11 '13 at 12:23

1 Answers1

0

You can disable script debugger using registry additionally with using "Silent" property, in c# that will look like (code taken from CSWebBrowserSuppressError). This can be done one time only on start of the application. As well take a look on @locster answer

var newValue = value ? "yes" : "no";

using (RegistryKey ieMainKey = Registry.CurrentUser.OpenSubKey(
     @"Software\Microsoft\Internet Explorer\Main", true))
{
     string keyvalue = ieMainKey.GetValue("Disable Script Debugger") as string;
     if (!keyvalue.Equals(newValue, StringComparison.OrdinalIgnoreCase))
     {
         ieMainKey.SetValue("Disable Script Debugger", newValue);
     }
}
Community
  • 1
  • 1
volody
  • 6,946
  • 3
  • 42
  • 54