C# – How to get the new window’s URL with WebBrowser

browserc++

I want to crawl a webpage. The problem is, this webpage has an encrypted link which can only be clicked. Using webBrowser.Navigate wont work. I managed to simulate a clicking action and it opened a new window. Now what I want is to get the new window's url.

private void Form1_Load(object sender, EventArgs e)
    {
        webBrowser1.Navigate(@"http://www.downarchive.ws/software/downloaders/795011-easy-mp3-downloader-4536.html");
    }

    private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
        HtmlElementCollection links = webBrowser1.Document.GetElementsByTagName("a");

        foreach (HtmlElement link in links)
        {
            if (link.GetAttribute("href").Contains(@"http://www.downarchive.ws/engine/go.php?url="))
            {
                link.InvokeMember("Click");
                break;
            }
        }
    }

    private void webBrowser1_NewWindow(object sender, CancelEventArgs e)
    {
        var webBrowser = (WebBrowser)sender;
        MessageBox.Show(webBrowser.Url.ToString());

    }

Best Solution

1) You don't need to invoke click. It is better to use Navigate method. When you invoke click, the link may open in new window, some additional javascript may be executed, etc.

2) If you need to get the url after all redirections, there is DocumentCompleted event:

WebBrowserDocumentCompletedEventHandler onDocumentCompleted = (sender, e) => {
    Uri theUlrThatYouNeed = e.Url;
    webBrowser1.DocumentCompleted -= onDocumentCompleted;
};
webBrowser1.DocumentCompleted += onDocumentCompleted;
webBrowser1.Navigate("your encrypted url");

3) If the link is open in external IE window, it's gone for you - you can't control the external browser and receive events from it. Sometimes, redirections can open new window. To prevent this, you can use the extended WebBrowser class:

namespace ExtendedWebBrowser {
[ComImport, TypeLibType(TypeLibTypeFlags.FHidden),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch),
Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D")]
public interface DWebBrowserEvents2 {
    /// <summary>
    /// 
    /// </summary>
    /// <param name="ppDisp">
    /// An interface pointer that, optionally, receives the IDispatch interface
    /// pointer of a new WebBrowser object or an InternetExplorer object.
    /// </param>
    /// <param name="Cancel">
    /// value that determines whether the current navigation should be canceled
    /// </param>
    /// <param name="dwFlags">
    /// The flags from the NWMF enumeration that pertain to the new window
    /// See http://msdn.microsoft.com/en-us/library/bb762518(VS.85).aspx.
    /// </param>
    /// <param name="bstrUrlContext">
    /// The URL of the page that is opening the new window.
    /// </param>
    /// <param name="bstrUrl">The URL that is opened in the new window.</param>
    [DispId(0x111)]
    void NewWindow3(
        [In, Out, MarshalAs(UnmanagedType.IDispatch)] ref object ppDisp,
        [In, Out] ref bool Cancel,
        [In] uint dwFlags,
        [In, MarshalAs(UnmanagedType.BStr)] string bstrUrlContext,
        [In, MarshalAs(UnmanagedType.BStr)] string bstrUrl);
}
public partial class WebBrowserEx : WebBrowser {
    AxHost.ConnectionPointCookie cookie;
    DWebBrowserEvent2Helper helper;
    [Browsable(true)]
    public event EventHandler<WebBrowserNewWindowEventArgs> NewWindow3;
    [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
    public WebBrowserEx() {
    }
    /// <summary>
    /// Associates the underlying ActiveX control with a client that can 
    /// handle control events including NewWindow3 event.
    /// </summary>
    [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
    protected override void CreateSink() {
        base.CreateSink();

        helper = new DWebBrowserEvent2Helper(this);
        cookie = new AxHost.ConnectionPointCookie(
            this.ActiveXInstance, helper, typeof(DWebBrowserEvents2));
    }
    /// <summary>
    /// Releases the event-handling client attached in the CreateSink method
    /// from the underlying ActiveX control
    /// </summary>
    [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
    protected override void DetachSink() {
        if (cookie != null) {
            cookie.Disconnect();
            cookie = null;
        }
        base.DetachSink();
    }
    /// <summary>
    ///  Raises the NewWindow3 event.
    /// </summary>
    protected virtual void OnNewWindow3(WebBrowserNewWindowEventArgs e) {
        if (this.NewWindow3 != null) {
            this.NewWindow3(this, e);
        }
    }
    private class DWebBrowserEvent2Helper : StandardOleMarshalObject, DWebBrowserEvents2 {
        private WebBrowserEx parent;
        public DWebBrowserEvent2Helper(WebBrowserEx parent) {
            this.parent = parent;
        }
        /// <summary>
        /// Raise the NewWindow3 event.
        /// If an instance of WebBrowser2EventHelper is associated with the underlying
        /// ActiveX control, this method will be called When the NewWindow3 event was
        /// fired in the ActiveX control.
        /// </summary>
        public void NewWindow3(ref object ppDisp, ref bool Cancel, uint dwFlags,
            string bstrUrlContext, string bstrUrl) {
            var e = new WebBrowserNewWindowEventArgs(bstrUrl, Cancel);
            this.parent.OnNewWindow3(e);
            Cancel = e.Cancel;
        }
    }
}
public class WebBrowserNewWindowEventArgs : EventArgs {
    public String Url { get; set; }
    public Boolean Cancel { get; set; }
    public WebBrowserNewWindowEventArgs(String url, Boolean cancel) {
        this.Url = url;
        this.Cancel = cancel;
    }
}
}

void WebBrowser_NewWindow(object sender, WebBrowserNewWindowEventArgs e) {
  if (!string.IsNullOrEmpty(e.Url)) {

    //Prevent new window
    e.Cancel = true;

    // Navigate to url from new window
    Navigate(e.Url);
  }
}

So, if you replace your WebBrowser control on its improved version, you will be able to prevent new window.