Load from IPersistMoniker takes long time to load unresolvable URL(从IPersistMoniker加载无法解析的URL需要很长时间)
问题描述
我正在通过IPersistMonikerLoad方法加载本地磁盘驱动器_test.htm文件。据我所知,它应该将路径添加到相对URL作为基本路径。问题是--它并没有这么做。相反,尝试解析来自Internet的路径需要很长时间,直到它放弃(大约20-30秒)。我想要的是,一旦检测到无法求解的路径(因为它无论如何都是本地磁盘文件),立即放弃。
这是我正在加载的示例HTML:
<html>
  <head>
    <script src="//test/test.js"></script>
  <head>
  <body>
    <img src="image.jpg">
    <img src="/image.jpg">
    <img src="//image.jpg">
  </body>
</html>
简化代码(C++Builder),不进行错误检查:
WideString      URL = "file:///" + StringReplace(ExtractFilePath(Application->ExeName), "\", "/", TReplaceFlags() << rfReplaceAll) + "_test.htm";
TCppWebBrowser* WB  = CppWebBrowser1;
DelphiInterface<IMoniker> pMoniker;
OleCheck(CreateURLMonikerEx(NULL, URL.c_bstr(), &pMoniker, URL_MK_UNIFORM));
DelphiInterface<IHTMLDocument2> diDoc2 = WB->Document;
DelphiInterface<IPersistMoniker> pPrstMnkr;
OleCheck(diDoc2->QueryInterface(IID_IPersistMoniker, (LPVOID*)&pPrstMnkr));
DelphiInterface<IBindCtx> pBCtx;
OleCheck(CreateBindCtx(0, &pBCtx));
pPrstMnkr->Load(0, pMoniker, pBCtx, STGM_READWRITE);
问题-image.jpg加载正常,但路径//test/test.js和/image.jpg和//image.jpg需要很长时间才能解决/加载。根据我的理解,CreateURLMonikerEx应该使用file:///path/to/executable/,并自动添加到这些路径,在这种情况下,它们将立即失败-例如file:///path/to/executable//test/test.js。这是不会发生的。
我还尝试将image.jpg移动到子文件夹,然后使用GetDisplayName和BindToStorage实现创建自定义IMoniker接口,这两个实现从自定义路径加载图像。但是,对于以//或/开头的路径,它不会执行相同的操作。即使我通过*ppszDisplayName参数在GetDisplayName中输出file:///path/to/executable/。
如何避免超时加载此类无法使用的链接(丢弃它们),或如上所述将它们重定向到本地路径?
我找到了在*ppszDisplayName中使用about:blank的部分解决方案,但它不加载具有有效路径image.jpg的图像,因为它将它们加载为about:image.jpg,这也是无效路径。
此外-我尝试使用Invoke方法(DISPID_AMBIENT_DLCONTROL)的实现添加IDocHostUIHandler接口,pVarResult->lVal = DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_RUNACTIVEXCTLS | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_FRAMEDOWNLOAD | DLCTL_FORCEOFFLINE;-它完全阻止图像下载,但仍会检查以//或/开头的链接的20-30秒。
推荐答案
在花了很多时间,在这里没有任何形式的指导之后,我相信当链接无效时,不可能避免这种等待20-30秒。我找到了另一个解决方案,如果有人想补充这个解决方案,请随意操作。 相反,我必须做的是创建更新-这不起作用!
以下代码不能很好地工作!问题是-它输了
<BODY>标记属性。加载后,Body标记变成完全空的。我 已使用IHTMLDocument2.write方法加载邮件。参见:Assigning IHTMLDocument2 instance to a TWebBrowser instance
CLSID_HTMLDocument(IHTMLDocument3或IHTMLDocument2接口)的实例,然后将文档加载到该容器中,并在对链接执行任何操作之前对其进行解析。有关说明,请参阅:
https://docs.microsoft.com/en-us/previous-versions/aa703592(v=vs.85)
这也有帮助:
How to load html contents from stream and then how to create style sheet to display the html file in preview pane (like HTML preview handler)
解析文档URL并修复无效URL后,即可保存/显示在实际TWebBrowser中。
粗略解决方案(C++Builder):
try
    {
    DelphiInterface<IHTMLDocument2> diDoc2;
    OleCheck(CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, (void**)&diDoc2));
    DelphiInterface<IPersistStreamInit> diPersist;
    OleCheck(diDoc2->QueryInterface(IID_IPersistStreamInit, (void**)&diPersist));
    OleCheck(diPersist->InitNew());
    DelphiInterface<IMarkupServices> diMS;
    OleCheck(diDoc2->QueryInterface(IID_IMarkupServices, (void**)&diMS));
    DelphiInterface<IMarkupPointer> diMkStart;
    DelphiInterface<IMarkupPointer> diMkFinish;
    OleCheck(diMS->CreateMarkupPointer(&diMkStart));
    OleCheck(diMS->CreateMarkupPointer(&diMkFinish));
    // ...Load from file or memory stream into your WideString here...
    DelphiInterface<IMarkupContainer> diMC;
    OleCheck(diMS->ParseString(WideString(MsgHTMLSrc).c_bstr(), 0, &diMC, diMkStart, diMkFinish));
    DelphiInterface<IHTMLDocument2> diDoc;
    OleCheck(diMC->QueryInterface(IID_PPV_ARGS(&diDoc)));
    DelphiInterface<IHTMLElementCollection> diCol;
    OleCheck(diDoc->get_all(&diCol));
    long ColLen = 0;
    OleCheck(diCol->get_length(&ColLen));
    for (int i = 0; i < ColLen; ++i)
        {
        DelphiInterface<IDispatch> diItem;
        diCol->item(OleVariant(i), OleVariant(i), &diItem);
        DelphiInterface<IHTMLElement> diElem;
        OleCheck(diItem->QueryInterface(IID_IHTMLElement, (void**)&diElem));
        WideString wTagName;
        OleCheck(diElem->get_tagName(&wTagName));
        if (StartsText("img", wTagName))
            {
            OleVariant vSrc;
            OleCheck(diElem->getAttribute(OleVariant("src"), 4, vSrc));
            // Make changes to vSrc here....
            // And save it back to src
            OleCheck(diElem->setAttribute(OleVariant("src"), vSrc, 0));
            }
        else if (StartsText("script", wTagName)) 
            {
            // More parsing here...
            }
        }
    }
catch (EOleSysError& e)
    {
    // Process exception as needed
    }
catch (Exception& e)
    {
    // Process exception as needed
    }
在完全解析所有必需元素(img/src、script/src、base/href等)之后。)保存并加载到TWebBrowser。
我现在只需查看已解析的IHTMLDocument2是否可以直接分配给TWebBrowser而无需再次加载它,但这是另一个问题(参见-Assigning IHTMLDocument2 instance to a TWebBrowser instance)
这篇关于从IPersistMoniker加载无法解析的URL需要很长时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:从IPersistMoniker加载无法解析的URL需要很长时间
				
        
 
            
        - 如何提取 __VA_ARGS__? 2022-01-01
 - 从父 CMakeLists.txt 覆盖 CMake 中的默认选项(...)值 2021-01-01
 - DoEvents 等效于 C++? 2021-01-01
 - 将 hdc 内容复制到位图 2022-09-04
 - 使用 __stdcall & 调用 DLLVS2013 中的 GetProcAddress() 2021-01-01
 - 将函数的返回值分配给引用 C++? 2022-01-01
 - OpenGL 对象的 RAII 包装器 2021-01-01
 - GDB 不显示函数名 2022-01-01
 - XML Schema 到 C++ 类 2022-01-01
 - 哪个更快:if (bool) 或 if(int)? 2022-01-01
 
						
						
						
						
						