2009-03-23 7 views
11

मैं .NET WebBrowser नियंत्रण का उपयोग कर रहा हूं। मुझे कैसे पता चलेगा कि कोई वेब पेज पूरी तरह से लोड हो जाता है?एचटीएमएल - मुझे कैसे पता चलेगा कि सभी फ्रेम कब लोड होते हैं?

मैं जानना चाहता हूं कि ब्राउज़र अब और डेटा नहीं ले रहा है। (वह क्षण जब आईई अपने स्टेटस बार में 'हो गया' लिखता है ...)।

नोट्स:

  • DocumentComplete/NavigateComplete घटनाओं एकाधिक फ्रेम वाला कोई वेब साइट के लिए एक से अधिक बार हो सकता है।
  • ब्राउज़र तैयार स्थिति समस्या को हल नहीं करती है।
  • मैंने फ्रेम संग्रह में फ्रेम की संख्या की जांच करने की कोशिश की है और फिर मुझे दस्तावेज़ पूर्ण घटना प्राप्त करने की संख्या की गिनती है लेकिन यह या तो काम नहीं करता है।
  • यह.WebBrowser.IsBusy या तो काम नहीं करता है। दस्तावेज़ पूर्ण हैंडलर में जांचते समय यह हमेशा 'झूठा' होता है।

उत्तर

1

यहाँ अंत में मेरे लिए काम किया है:

 public bool WebPageLoaded 
    { 
     get 
     { 
      if (this.WebBrowser.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete) 
       return false; 

      if (this.HtmlDomDocument == null) 
       return false; 

      // iterate over all the Html elements. Find all frame elements and check their ready state 
      foreach (IHTMLDOMNode node in this.HtmlDomDocument.all) 
      { 
       IHTMLFrameBase2 frame = node as IHTMLFrameBase2; 
       if (frame != null) 
       { 
        if (!frame.readyState.Equals("complete", StringComparison.OrdinalIgnoreCase)) 
         return false; 

       } 
      } 

      Debug.Print(this.Name + " - I think it's loaded"); 
      return true; 
     } 
    } 

प्रत्येक दस्तावेज़ पूरा घटना मैं सभी एचटीएमएल तत्व पर चलाने के लिए और सभी फ्रेम उपलब्ध जाँच (मैं इसे अनुकूलित किया जा सकता है पता है) पर। प्रत्येक फ्रेम के लिए मैं इसकी तैयार स्थिति की जांच करता हूं। यह बहुत भरोसेमंद है लेकिन जैसे ही जेफमैफोन ने कहा कि मैंने पहले से ही ऐसी साइटें देखी हैं जो कुछ आंतरिक रीफ्रेश ट्रिगर करती हैं। लेकिन उपरोक्त कोड मेरी आवश्यकताओं को पूरा करता है।

संपादित करें: प्रत्येक फ्रेम में इसके अंदर फ्रेम हो सकते हैं, इसलिए मुझे लगता है कि यह कोड प्रत्येक फ्रेम की स्थिति को पुन: जांचने के लिए अपडेट किया जाना चाहिए।

0

क्या आपने WebBrowser.IsBusy संपत्ति का प्रयास किया है?

+1

हाँ। जब भी दस्तावेज़ पूर्ण हैंडलर को कॉल किया जाता है तो वेब ब्राउजर व्यस्त होने का दावा नहीं करता है ... –

0

फ्रेम पूर्ण होने पर ध्वज सेट करने के लिए प्रत्येक फ्रेम में जावास्क्रिप्ट का उपयोग करने के बारे में, और फिर झंडे पर सी # देखें?

+0

मैं ब्राउजर पर जा रहे प्रत्येक साइट के डीओएम पेड़ में हेरफेर नहीं करना चाहता हूं। लेकिन मान लीजिए कि मैं आपके समाधान का उपयोग करता हूं, मैं इसे जावास्क्रिप्ट में कैसे कर सकता हूं? –

+0

मुझे जेएस बनाम सी # में ऐसा करने का लाभ नहीं दिख रहा है। –

0

मैं तुम्हारे लिए एक विकल्प नहीं है, लेकिन मुझे आश्चर्य है अगर IsBusy संपत्ति जा रहा है दस्तावेज़ पूरा हैंडलर है क्योंकि हैंडलर अभी भी चल रहा है और इसलिए WebBrowser नियंत्रण तकनीकी रूप से अभी भी 'व्यस्त' है दौरान tru ई।

सबसे आसान समाधान एक लूप होना होगा जो प्रत्येक 100 एमएस या तब तक निष्पादित करेगा जब तक कि IsBusy ध्वज रीसेट हो (त्रुटियों के मामले में अधिकतम निष्पादन समय के साथ)। निश्चित रूप से यह मानता है कि IsBusy पृष्ठ लोडिंग के दौरान किसी भी समय false पर सेट नहीं किया जाएगा।

यदि दस्तावेज़ पूर्ण हैंडलर किसी अन्य थ्रेड पर निष्पादित करता है, तो आप अपने मुख्य धागे को सोने के लिए भेजने के लिए लॉक का उपयोग कर सकते हैं और इसे दस्तावेज़ पूर्ण थ्रेड से जगा सकते हैं। फिर IsBusy ध्वज की जांच करें, मुख्य थ्रेड को फिर से लॉक करना अभी भी true है।

+0

लेकिन IsBusy बहुत जल्दी झूठी पर सेट है। उदाहरण के लिए, यदि आपके पास वेब पेज में छह फ्रेम हैं, जब पहला फ्रेम लोडिंग पूर्ण करता है, तो IsBusy DocumentComplete ईवेंट पर गलत है। –

+0

प्रत्येक फ्रेम को अपना वेबब्रोसर (IWebBrowser2 कार्यान्वयन) मिलता है। संभवतः IsBusy विशेषता केवल विशिष्ट फ्रेम पर लागू होती है। और जब यह पूरा हो जाए, तो यह अब व्यस्त नहीं होगा। –

0

मुझे यकीन है कि यह काम करते हैं लेकिन इस तरह अपने frameset पर एक JavaScript "ऑनलोड" घटना को जोड़ने की कोशिश करता हूँ नहीं कर रहा हूँ:

function everythingIsLoaded() { alert("everything is loaded"); } 
var frameset = document.getElementById("idOfYourFrameset"); 
if (frameset.addEventListener) 
    frameset.addEventListener('load',everythingIsLoaded,false); 
else 
    frameset.attachEvent('onload',everythingIsLoaded); 
+0

मैं यह जानना चाहता हूं कि सभी फ़्रेम किसी भी वेबसाइट के लिए लोड किए गए हैं, इसलिए मुझे नहीं पता कि इसमें कौन से फ्रेम शामिल हैं। –

+0

आपको फ्रेम फ्रेम (सभी फ्रेम के पैरेंट) पर ऐसा करना चाहिए, प्रत्येक फ्रेम पर नहीं। इसे किसी भी वेबसाइट से प्राप्त करना बहुत आसान है: document.getElementsByTagName ('frameset') [0] – paulgreg

0

आप jQuery का उपयोग कर सकते हैं? फिर आप आसानी से लक्ष्य फ्रेम पर फ्रेम तैयार घटनाओं को बांध सकते हैं। दिशानिर्देशों के लिए this उत्तर देखें। यह blog post इसके बारे में भी एक चर्चा है। अंत में plug-in है जिसका आप उपयोग कर सकते हैं।

$("iframe").size() 

और फिर आप गिनती कितनी बार आइफ्रेम तैयार गतिविधि सक्रिय कर दिया गया है

विचार है कि आप का उपयोग कर वेब पेज में फ्रेम की संख्या की गिनती है।

0

आपको बाहरी वेब पेज के साथ-साथ प्रत्येक फ्रेम के लिए पहले सेविगेट और दस्तावेज़ पूर्ण ईवेंट मिलेगा। आप जानते हैं कि जब आप बाहरी वेबपृष्ठ के लिए दस्तावेज़ पूर्ण घटना प्राप्त करते हैं तो आप किया जाता है। यह निर्धारित करने के लिए आपको IWebBrowser2::TopLevelContainer() के प्रबंधित समकक्ष का उपयोग करने में सक्षम होना चाहिए।

सावधान रहें, हालांकि, वेबसाइट स्वयं कभी भी फ्रेम फ्रेम नेविगेशन को किसी भी समय ट्रिगर कर सकती है, इसलिए आप कभी नहीं जानते कि कोई पृष्ठ हमेशा के लिए किया जाता है या नहीं। सबसे अच्छा आप कर सकते हैं कि आप पहले देखे गए सभी नवागेटों की गिनती रखें और जब आप दस्तावेज़कंपलेट प्राप्त करते हैं तो गिनती कम करें।

संपादित करें: यहां प्रबंधित दस्तावेज़ हैं: TopLevelContainer

+1

मैंने पहले नेविगेट्स और वेबब्राउज़र नियंत्रण में दस्तावेज़ को पूरा करने की कोशिश की। यह सिंक नहीं किया गया है ... :(दस्तावेज़ से पूर्ण नेविगेट करने से पहले और भी बहुत कुछ है। [शायद इसे कैशिंग या डुप्लिकेट फ्रेम के साथ करना है। मुझे नहीं पता] –

+0

दस्तावेज़ के बारे में पूरी घटना: सी # WebBrowser आपको दस्तावेज़ ऑब्जेक्ट नहीं मिलता है जो अभी लोड हो रहा है। बस यूआरएल। तो आप अपने ब्राउज़र कंटेनर पर नहीं जा सकते। –

2

कुछ जब पेज पूरी तरह से भरी हुई है (फ्रेम सहित) कर मेरे दृष्टिकोण कुछ इस तरह है: मेरे अन्य तरीकों से

using System.Windows.Forms; 
    protected delegate void Procedure(); 
    private void executeAfterLoadingComplete(Procedure doNext) { 
     WebBrowserDocumentCompletedEventHandler handler = null; 
     handler = delegate(object o, WebBrowserDocumentCompletedEventArgs e) 
     { 
      ie.DocumentCompleted -= handler; 
      Timer timer = new Timer(); 
      EventHandler checker = delegate(object o1, EventArgs e1) 
      { 
       if (WebBrowserReadyState.Complete == ie.ReadyState) 
       { 
        timer.Dispose(); 
        doNext(); 
       } 
      }; 
      timer.Tick += checker; 
      timer.Interval = 200; 
      timer.Start(); 
     }; 
     ie.DocumentCompleted += handler; 
    } 

मुझे पता चला कुछ -s "नहीं":

  • चम्मच मोड़ने की कोशिश न करें ... ;-)
  • दस्तावेज़कंपलेट, फ्रेम्स, एचटीएमएल विन्डो.लोड घटनाओं का उपयोग करके विस्तृत निर्माण करने की कोशिश न करें। काम करते समय आपका समाधान नाजुक होगा।
  • के बजाय System.Timers.Timer का उपयोग न करें, अगर आप ऐसा करते हैं तो अजीब त्रुटियों में अजीब त्रुटियां शुरू हो जाएंगी, क्योंकि आपके बाकी ऐप पर टाइमर चल रहा है।
  • दस्तावेज़ के बिना केवल टाइमर का उपयोग न करें क्योंकि यह आपके पृष्ठ से पहले भी लोड हो सकता है और आपके कोड को समय-समय पर निष्पादित करेगा।
2

यहाँ कैसे मैं अपने आवेदन में समस्या हल हो गई है:

private void wbPost_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
{ 
    if (e.Url != wbPost.Url) 
     return; 
    /* Document now loaded */ 
} 
+0

यदि आप करते हैं जैसे कि नेविगेशन बार में एक क्लिक और इससे कारण है कि एक नई वेबसाइट पुनः लोड हो गई है फ्रेम/आईफ्रेम में, आप इस समाधान से खुश नहीं होंगे। –

0

मैं सिर्फ webBrowser.StatusText विधि का उपयोग करें। जब यह कहता है "हो गया" सबकुछ भरा हुआ है! या क्या मुझे कुछ याद आ रहा है?

+0

अगर iframe –

2

यहां मेरा परीक्षण संस्करण है। बस इसे अपने DocumentCompleted Event Handler बनाएं और उस कोड को रखें जिसे आप केवल विधि OnWebpageReallyLoaded() में बुलाएं। प्रभावी रूप से, यह दृष्टिकोण निर्धारित करता है कि पृष्ठ 200ms के लिए स्थिर कब है और फिर इसकी बात है।

// event handler for when a document (or frame) has completed its download 
Timer m_pageHasntChangedTimer = null; 
private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { 
    // dynamic pages will often be loaded in parts e.g. multiple frames 
    // need to check the page has remained static for a while before safely saying it is 'loaded' 
    // use a timer to do this 

    // destroy the old timer if it exists 
    if (m_pageHasntChangedTimer != null) { 
     m_pageHasntChangedTimer.Dispose(); 
    } 

    // create a new timer which calls the 'OnWebpageReallyLoaded' method after 200ms 
    // if additional frame or content is downloads in the meantime, this timer will be destroyed 
    // and the process repeated 
    m_pageHasntChangedTimer = new Timer(); 
    EventHandler checker = delegate(object o1, EventArgs e1) { 
     // only if the page has been stable for 200ms already 
     // check the official browser state flag, (euphemistically called) 'Ready' 
     // and call our 'OnWebpageReallyLoaded' method 
     if (WebBrowserReadyState.Complete == webBrowser.ReadyState) { 
      m_pageHasntChangedTimer.Dispose(); 
      OnWebpageReallyLoaded(); 
     } 
    }; 
    m_pageHasntChangedTimer.Tick += checker; 
    m_pageHasntChangedTimer.Interval = 200; 
    m_pageHasntChangedTimer.Start(); 
} 

OnWebpageReallyLoaded() { 
    /* place your harvester code here */ 
} 
+0

है तो नकारात्मक धन्यवाद! यह मेरे लिए पूरी तरह से काम कर रहा है। – selegnasol

0

के लिए IE.readyState = READYSTATE_COMPLETE काम करना चाहिए की जांच कर रहा है, लेकिन आप के लिए विश्वसनीय साबित नहीं करता है, तो यह है कि है और आप सचमुच "पल लिखते हैं जब IE अपनी स्थिति पट्टी में 'पूर्ण' 'जानना चाहते हैं, तो आप क्या कर सकते हैं IE.StatusText तक एक लूप "हो गया" है।

संबंधित मुद्दे