我正在使用IHTMLDocument2来爬行一组网站。我正在这样创建IHTMLDocument2实例:

    var
      myDownload : TDownLoadURL;
      doc: OleVariant;
    (...)
      myDownload:= TDownLoadURL.Create(nil);
      with myDownload do
      begin
        URL:=myURL;
        Filename:= GetTempDirectory+'temp_download_url_complete2.txt';
        ExecuteTarget(nil);
      end;
(...)
      doc := coHTMLDocument.Create as IHTMLDocument2;
      doc.write(html);
      doc.close;
(...)


有一个特定的网站会弹出以下消息:


为了使本网站能够为您提供个性化信息,
您是否允许它在您的计算机上放一个小文件(称为Cookie)
电脑?


我已经更改了操作系统(Windows 2008 SE)的Internet选项,以阻止cookie而不提示您,但是消息不断出现。如何以静默方式创建IHTMLDocument2?

最佳答案

如果需要取消显示IHTMLDocument用户界面或用户通知,则需要同时实现IOleClientSite和定义为DISPID_AMBIENT_DLCONTROL的环境属性。
从文档"Download Control"


主机可以控制下载的某些方面,例如框架,图像,Java,
等等-通过同时实现IOleClientSite和环境属性
定义为DISPID_AMBIENT_DLCONTROL。当主机的IDispatch :: Invoke
在dispidMember设置为DISPID_AMBIENT_DLCONTROL的情况下调用方法
应在其中放置零或以下值的组合
pvarResult。


在这种情况下,您需要的标志是DLCTL_SILENT(也可能是DLCTL_NO_SCRIPTS)。

如前所述,如果您希望从文档中获取事件通知(例如,例如IDispatch),主机还应该实现.InvokeIPropertyNotifySink)以及可选的DISPID_READYSTATE(或其他COM event sink对象)。

查看EmbeddedWB来源以了解如何实现。特别是IEParser.pasUI_Less.pas。它已经完全满足您的需求。



这是一个基于UI_Less的简化演示(未实现IPropertyNotifySink):

uses ..., ActiveX, MSHTML;

const
  DISPID_AMBIENT_DLCONTROL = (-5512);

type
  TUILess = class(TComponent, IUnknown, IDispatch, IOleClientSite)
    protected
    // IDispatch
    function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
      Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HRESULT; stdcall;
    // IOleClientSite
    function SaveObject: HRESULT; stdcall;
    function GetMoniker(dwAssign: Longint; dwWhichMoniker: Longint;
      out mk: IMoniker): HRESULT; stdcall;
    function GetContainer(out container: IOleContainer): HRESULT; stdcall;
    function ShowObject: HRESULT; stdcall;
    function OnShowWindow(fShow: BOOL): HRESULT; stdcall;
    function RequestNewObjectLayout: HRESULT; stdcall;
  end;

implementation

function TUILess.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
  Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HRESULT;
const
  DLCTL_NO_SCRIPTS = $00000080;
  DLCTL_NO_JAVA = $00000100;
  DLCTL_NO_RUNACTIVEXCTLS = $00000200;
  DLCTL_NO_DLACTIVEXCTLS = $00000400;
  DLCTL_DOWNLOADONLY = $00000800;
  DLCTL_SILENT = $40000000;
var
  I: Integer;
begin
  if DISPID_AMBIENT_DLCONTROL = DispID then
  begin
    I := DLCTL_DOWNLOADONLY + DLCTL_NO_SCRIPTS +
      DLCTL_NO_JAVA + DLCTL_NO_DLACTIVEXCTLS +
      DLCTL_NO_RUNACTIVEXCTLS +
      DLCTL_SILENT;
    PVariant(VarResult)^ := I;
    Result := S_OK;
  end
  else
    Result := DISP_E_MEMBERNOTFOUND;
end;

function TUILess.SaveObject: HRESULT;
begin
  Result := E_NOTIMPL;
end;

function TUILess.GetMoniker(dwAssign: Longint; dwWhichMoniker: Longint;
  out mk: IMoniker): HRESULT;
begin
  Result := E_NOTIMPL;
end;

function TUILess.GetContainer(out container: IOleContainer): HRESULT;
begin
  Result := E_NOTIMPL;
end;

function TUILess.ShowObject: HRESULT;
begin
  Result := E_NOTIMPL;
end;

function TUILess.OnShowWindow(fShow: BOOL): HRESULT;
begin
  Result := E_NOTIMPL;
end;

function TUILess.RequestNewObjectLayout: HRESULT;
begin
  Result := E_NOTIMPL;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
  cHTML: WideString = '<b>test</b><script>alert("boo")</script>';
var
  Doc: IHTMLDocument2;
  DocClientSite: TUILess;
begin
  DocClientSite := TUILess.Create(nil);
  try
    Doc := coHTMLDocument.Create as IHTMLDocument2;
    try
      (Doc as IOleObject).SetClientSite(DocClientSite);
      (Doc as IOleControl).OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL); // Invoke
      OleVariant(Doc).write(cHTML);
      Doc.close;
      ShowMessage(Doc.body.innerHtml); // Test
    finally
      (Doc as IOleObject).SetClientSite(nil);
      Doc := nil;
    end;
  finally
    DocClientSite.Free;
  end;
end;

10-04 19:16