2009-05-08 12 views
14

इस सवाल का लेखन शुरू करने से पहले, मैं निम्नलिखितWebBrowser नियंत्रण दस्तावेज़ का उपयोग कैसे करें C# में पूर्ण घटना?

// 1. navigate to page 
// 2. wait until page is downloaded 
// 3. read and write some data from/to iframe 
// 4. submit (post) form 

समस्या को हल करने गई थी कि यदि एक iframe एक वेब पेज पर मौजूद है, DocumentCompleted घटना तो एक बार फिर निकाल दिया जाएगा (के बाद प्रत्येक दस्तावेज़ पूरा हो चुका है कोशिश कर रहा था,)। यह अत्यधिक संभावना थी कि कार्यक्रम ने डोम से डेटा पढ़ने की कोशिश की होगी जो पूरा नहीं हुआ था और स्वाभाविक रूप से - असफल रहा।

लेकिन इस प्रश्न लिखने अचानक जबकि 'अगर' राक्षस मुझे प्रेरित है, और मैं समस्या fix'ed, कि मैं हल करने के लिए कोशिश कर रहा था। चूंकि मैं इसे Google में विफल रहा, मैंने सोचा कि इसे यहां पोस्ट करना अच्छा लगेगा।

private int iframe_counter = 1; // needs to be 1, to pass DCF test 
    public bool isLazyMan = default(bool); 

    /// <summary> 
    /// LOCK to stop inspecting DOM before DCF 
    /// </summary> 
    public void waitPolice() { 
     while (isLazyMan) Application.DoEvents(); 
    } 

    private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) { 
     if(!e.TargetFrameName.Equals("")) 
      iframe_counter --; 
     isLazyMan = true; 
    } 

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { 
     if (!((WebBrowser)sender).Document.Url.Equals(e.Url)) 
      iframe_counter++; 
     if (((WebBrowser)sender).Document.Window.Frames.Count <= iframe_counter) {//DCF test 
      DocumentCompletedFully((WebBrowser)sender,e); 
      isLazyMan = false; 
     } 
    } 

    private void DocumentCompletedFully(WebBrowser sender, WebBrowserDocumentCompletedEventArgs e){ 
     //code here 
    } 

अब कम से कम, मेरा 5 एम हैक ठीक काम कर रहा है।

शायद मैं वास्तव में Google या MSDN से पूछताछ में असफल रहा हूं, लेकिन मुझे नहीं मिल रहा है: "Webbrowser नियंत्रण दस्तावेज़ का उपयोग कैसे करें C# में पूर्ण घटना का उपयोग करें?"

टिप्पणी: वेबcontrol के बारे में बहुत कुछ सीखने के बाद, मैंने पाया कि यह फनकी सामान करता है।

भले ही आप यह पता लगाते हैं कि दस्तावेज़ पूरा हो गया है, ज्यादातर मामलों में यह हमेशा के लिए ऐसा नहीं रहेगा। पेज अपडेट कई तरीकों से किया जा सकता है - फ़्रेम रीफ्रेश, अनुरोध या सर्वर साइड पुश जैसे AJAX (आपको कुछ नियंत्रण होना चाहिए जो एसिंक्रोनस संचार का समर्थन करता है और इसमें HTML या जावास्क्रिप्ट इंटरऑप है)। इसके अलावा कुछ iframes कभी लोड नहीं होंगे, इसलिए उनके लिए हमेशा के लिए इंतजार करना सबसे अच्छा विचार नहीं है।

if (e.Url != wb.Url) 
+0

दस्तावेज़ पूर्ण घटना के दौरान IsBusy संपत्ति की स्थिति क्या है? – AMissico

+0

जैसे ही पहला फ्रेम तैयार हो गया है, IsBusy झूठी वापसी करेगा। – Margus

+1

बस एक नोट, आपका कोड एकाधिक सामान्य फ्रेम के साथ काम नहीं करेगा। –

उत्तर

14

आप एजेक्स कॉल भी जानना चाहेंगे।

इसके उपयोग पर विचार:

private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
{ 
    string url = e.Url.ToString(); 
    if (!(url.StartsWith("http://") || url.StartsWith("https://"))) 
    { 
      // in AJAX 
    } 

    if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath) 
    { 
      // IFRAME 
    } 
    else 
    { 
      // REAL DOCUMENT COMPLETE 
    } 
} 
+2

+1, लेकिन अन्य भाग में वास्तविक दस्तावेज़ शामिल होगा, जहां स्थिति होगी IFRAME – pug

+0

@pug मैंने इसे इंगित करने के लिए पोस्ट संपादित किया है। – AaronLS

0

मैं ऐसी ही कुछ करना था:

मैं का उपयोग कर समाप्त हो गया। मैं जो करता हूं वह सीधे ShDocVw का उपयोग करता है (मेरे प्रोजेक्ट में सभी आवश्यक इंटरऑप असेंबली का संदर्भ जोड़ना)। फिर, मैं अपने फॉर्म में WebBrowser नियंत्रण नहीं जोड़ता, लेकिन AXShDocVw.AxWebBrowser नियंत्रण।

नेविगेट और इंतजार मैं निम्न विधि करने के लिए उपयोग करने के लिए:

private void GotoUrlAndWait(AxWebBrowser wb, string url) 
{ 
    object dummy = null; 
    wb.Navigate(url, ref dummy, ref dummy, ref dummy, ref dummy); 

    // Wait for the control the be initialized and ready. 
    while (wb.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE) 
     Application.DoEvents(); 
} 
+2

बस इसके लिए एक नोट, यह असफल हो जाएगा कि पृष्ठ अजाक्स का उपयोग कर रहा है, क्योंकि पृष्ठ कभी भी "पूर्ण" नहीं होगा। –

3

मैं ऑनलाइन इस समस्या का एक काम कर समाधान खोजने के लिए अभी तक है। उम्मीद है कि यह इसे शीर्ष पर लाएगा और हर किसी को ट्विकिंग के महीनों को बचाएगा जिसे मैंने हल करने की कोशिश की थी, और इसके साथ जुड़े किनारे के मामले। मैंने पिछले कुछ सालों में इस मुद्दे पर लड़ा है क्योंकि माइक्रोसॉफ्ट ने आईएसबीसी और document.readystate की कार्यान्वयन/विश्वसनीयता को बदल दिया है। आईई 8 के साथ, मुझे निम्नलिखित समाधान का सहारा लेना पड़ा। यह कुछ अपवादों के साथ मार्गस से प्रश्न/उत्तर के समान है। मेरा कोड नेस्टेड फ्रेम, जावास्क्रिप्ट/AJAX अनुरोध और मेटा-रीडायरेक्ट को संभालेगा। मैंने स्पष्टता के लिए कोड को सरल बना दिया है, लेकिन मैं वेबपृष्ठ को रीसेट करने के लिए टाइमआउट फ़ंक्शन (शामिल नहीं) का भी उपयोग करता हूं, इसके बाद 5 मिनट domAccess अभी भी गलत के बराबर है।

private void m_WebBrowser_BeforeNavigate(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel) 
{ 
    //Javascript Events Trigger a Before Navigate Twice, but the first event 
    //will contain javascript: in the URL so we can ignore it. 
    if (!URL.ToString().ToUpper().StartsWith("JAVASCRIPT:")) 
    { 
     //indicate the dom is not available 
     this.domAccess = false; 
     this.activeRequests.Add(URL); 
    } 
} 

private void m_WebBrowser_DocumentComplete(object pDisp, ref object URL) 
{ 

    this.activeRequests.RemoveAt(0); 

    //if pDisp Matches the main activex instance then we are done. 
    if (pDisp.Equals((SHDocVw.WebBrowser)m_WebBrowser.ActiveXInstance)) 
    { 
     //Top Window has finished rendering 
     //Since it will always render last, clear the active requests. 
     //This solves Meta Redirects causing out of sync request counts 
     this.activeRequests.Clear(); 
    } 
    else if (m_WebBrowser.Document != null) 
    { 
     //Some iframe completed dom render 
    } 

    //Record the final complete URL for reference 
    if (this.activeRequests.Count == 0) 
    { 
     //Finished downloading page - dom access ready 
     this.domAccess = true; 
    } 
} 
+0

क्या आप शायद पिछले आईई संस्करणों के अंतरों पर विस्तार कर सकते हैं? – peterchen

+1

वेबब्रोसर स्वचालन के शुरुआती वर्षों में मैं केवल दस्तावेज़ पूर्ण कार्य का उपयोग करने में सक्षम था - यह लगभग 2002/3 - यानी 5.5/6 था। यदि आपकी पीडीआईएसपी ऑब्जेक्ट शीर्ष दस्तावेज़ विंडो से मेल खाती है तो दस्तावेज़ पूरी तरह से तैयार था और इसे हमेशा निकाल दिया जाता था। इन दिनों ~ जब ~ यह आग लगती है तो आपको आश्वासन दिया जा सकता है कि आपका दस्तावेज़ तैयार है, लेकिन आप कैसे जानते हैं कि एक असुरक्षित टाइमआउट के बिना एसिंक घटना मॉडल में कोई घटना नहीं होती है? IsBusy माउस कर्सर को बदलने के लिए एक अच्छा संकेतक होता था, लेकिन मैंने देखा है कि IsBusy 7 और 8. के ​​हाल के संस्करण में अनिश्चित काल तक रहता है। –

+0

और यदि मुझे सही याद है तो AJAX अनुरोधों ने इन घटनाओं को IE6 तक ठीक से ट्रिगर नहीं किया है, और तब से यानी 7 या ie8 वे अब घटनाओं नेविगेट करने से पहले डुप्लिकेट ट्रिगर करते हैं। और नेविगेट पूर्ण या पूरी घटनाओं को डाउनलोड करने से भी परेशान न हों क्योंकि वे नेविगेशन लाइफसाइकिल की समापन स्थिति निर्धारित करने में आपकी सहायता नहीं करेंगे। –

2

Thorsten के विपरीत मैं ShDocVw उपयोग करने के लिए नहीं था, लेकिन क्या मुझे पाश readyState जाँच जोड़ने और आवेदन उपयोग कर रहा था फर्क था।DoEvents() तैयार नहीं है। यहाँ मेरी कोड है:

 this.webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted); 
     foreach (var item in this.urlList) // This is a Dictionary<string, string> 
     { 
      this.webBrowser.Navigate(item.Value); 
      while (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete) 
      { 
       Application.DoEvents(); 
      } 
     } 

और मैं पिछले के साथ करता है, तो/किसी और उपयोगकर्ता की टिप्पणी प्रति बदली WebBrowser_DocumentCompleted के परिणामों की जाँच के लिए युकी के समाधान के लिए इस्तेमाल किया, हालांकि:

 private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
    { 
     string url = e.Url.ToString(); 
     var browser = (WebBrowser)sender; 

     if (!(url.StartsWith("http://") || url.StartsWith("https://")))  
     {    
      // in AJAX  
     } 
     if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath)  
     { 
      // IFRAME   
     }  
     else  
     {    
      // REAL DOCUMENT COMPLETE 
      // Put my code here 
     } 
    } 

एक आकर्षण की तरह काम किया :)

-1

बस एक छोटे से सुधार के बारे में एक पंक्ति या दो ड्रॉप करने का विचार किया जो FeiBao के कोड के संयोजन के साथ काम करता है। विचार वेबपृष्ठ में एक ऐतिहासिक (जावास्क्रिप्ट) वैरिएबल इंजेक्ट करना है और इसका उपयोग यह पता लगाने के लिए करें कि बाद में कौन से दस्तावेज़ पूर्ण घटनाएं असली सौदा है। मुझे संदेह है कि यह बुलेटप्रूफ है लेकिन इसने उस दृष्टिकोण के मुकाबले सामान्य रूप से अधिक भरोसेमंद काम किया है जिसकी कमी है। कोई टिप्पणी स्वागत है। यहां बॉयलरप्लेट कोड है:

void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) 
    { 
     string url = e.Url.ToString(); 
     var browser = (WebBrowser)sender; 

     if (!(url.StartsWith("http://") || url.StartsWith("https://"))) 
     { 
      // in AJAX  
     } 
     if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath) 
     { 
      // IFRAME   
     } 
     else if (browser.Document != null && (bool)browser.Document.InvokeScript("eval", new object[] { @"typeof window.YourLandMarkJavascriptVariableHere === 'undefined'" })) 
     { 
      ((IHTMLWindow2)browser.Document.Window.DomWindow).execScript("var window.YourLandMarkJavascriptVariableHere = true;"); 

      // REAL DOCUMENT COMPLETE 
      // Put my code here 
     } 
    }