How to Fix the Memory Leak in IE WebBrowser Control?

my app was also constantly consuming memory when navigating, and not releasing anymore. i fount the solution for me here: http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/88c21427-e765-46e8-833d-6021ef79e0c8

for completeness ill post the notable excerpt:

-- in class definition

    [DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
    internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);

    [DllImport("KERNEL32.DLL", EntryPoint = "GetCurrentProcess", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
    internal static extern IntPtr GetCurrentProcess();

-- code to call when you want to reduce the memory

        IntPtr pHandle = GetCurrentProcess();
        SetProcessWorkingSetSize(pHandle, -1, -1);

all honors to: http://social.msdn.microsoft.com/profile/mike_t2e/?type=forum&referrer=http://social.msdn.microsoft.com/Forums/en-US/ieextensiondevelopment/thread/88c21427-e765-46e8-833d-6021ef79e0c8 for posting the solution.

and http://ict-engineer.blogspot.com/2010/10/net-webbrowser-control-memory-leak.html for SEO'ing it right, so i could find it ;)

greetings

edit: if this helps you to quickly solve an issu - good. but you should overthing your application design, the pattern you use if any , refactore the thing if you build onto that much longer ....


I just created a simple app with a web browser control to try and duplicate your results. What I found was that yes, every time you navigate to a page, the memory being used increases significantly. HOWEVER, this is NOT a memory leak, because if you keep navigating, you'll see that after a short while, the memory drops significantly, indicating that the garbage collector did it's thing. To prove it, I forced the Garbage Collector to collect after every time I called Navigate, and the overall memory used stayed put at almost the same amount after every navigate call.

So while it DOES rack up memory every time you "Navigate" it's NOT a memory leak, and you the memory will be released. If it's raking up too quickly, just call GC.Collect();


The BASIC IDEA is,

"Kill myself, and reborn."

Windows will solve all memory problems.

but if you Close your application first, you can't start a new one.

So, START A NEW ONE, and CLOSE THE OLDER ONE.

First turn on a new one, and turn off an old one.


public void SOLVE_ALL_MY_MEMORY_PROBLEM()
{
  System.Diagnostics.Process.Start("MyProgram.exe");
  Application.Exit();
}

https://www.youtube.com/watch?v=aTBlKRzNf74

If there is a parameter,

public void SOLVE_ALL_MY_MEMORY_PROBLEM()
{
  System.Diagnostics.Process.Start("MyProgram.exe", "PARA_para_dance");
  Application.Exit();
}

Go to Program.cs

    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        if(args.Count() > 0)
            Application.Run(new Form1(args[0]));
        else
            Application.Run(new Form1());
    }

and, Go to Form1.cs and make another Form1()

    public Form1()
    {
        InitializeComponent();
    }

    public Form1(string dance_name)
    {
        InitializeComponent();

        ...
    }

or you can use temp file !!!


There's an alternative control that uses Gecko (The engine Firefox uses) instead of Trident and works very well with the MSHTML interfaces.

Your pages will render in Gecko, and you'll have complete control over the settings, plugins, security and any other customisable features of a browser.

The downside is that you'll need to ship Gecko with your app, I last used the equivalent of Firefox 2 and it was around 8MB.

I released an app quite a while ago that compared IE and Firefox rendering alongside each other, both updating as you edited the CSS. I didn't run into the memory problems you've had with the web browser control, but I found the Gecko control very easy to work with. It doesn't have the same managed wrapper class that the .net WebBrowser control has, but it's easy enough to work around that.


According to MSDN, The System.Windows.Forms.WebBrowser control is a managed wrapper for the ActiveX WebBrowser control, and uses whichever version of the control is installed on the user's computer.

You can find Dispose(bool) method in metadata of WebBrowser class(Press F12 in Visual Stuio) to release unmanaged resource.(NOT Dispose())

The code here

protected override void Dispose(bool disposing) {
    if (disposing) {
        if (htmlShimManager != null)
        {
            htmlShimManager.Dispose();
        }
        DetachSink();
        ActiveXSite.Dispose();
    }
    base.Dispose(disposing);
}

But if you try to call WebBrowser.Dispose(bool), compiler error CS1540 is shown.

WebBrowser class supports Dispose(bool) method, BUT we can't use that. I think WebBrowser class was designed by wrong way.

I have a idea to call WebBrowser.Dispose(true). IT IS VERY SIMPLE! but it's not a good way.

Sample Code in here(3 Buttons, and 1 TextBox need)

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Test_20170308_01
{
    public partial class Form1 : Form
    {
        [DllImportAttribute("kernel32.dll", EntryPoint = "SetProcessWorkingSetSize", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
        private static extern int SetProcessWorkingSetSize(IntPtr process, int minimumWorkingSetSize, int maximumWorkingSetSize);
        public static void FlushMemory()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
            }
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void addWeb()
        {
            WebBrowserD webBrowser1 = new WebBrowserD();
            webBrowser1.Size = new Size(1070, 585);
            this.Controls.Add(webBrowser1);
            webBrowser1.Navigate("about:blank");
        }

        private void RemoveWeb()
        {
            foreach (Control ctrl in this.Controls)
            {
                if (ctrl is  WebBrowserD)
                {
                    WebBrowserD web = (WebBrowserD)ctrl;
                    this.Controls.Remove(ctrl);
                    web.Navigate("about:blank");
                    web.Dispose(true);
                    FlushMemory();
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            addWeb();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            RemoveWeb();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            foreach (Control ctrl in this.Controls)
            {
                if (ctrl is WebBrowserD)
                {
                    WebBrowserD axweb = (WebBrowserD)ctrl;
                    axweb.Navigate(textBox1.Text);
                    FlushMemory();
                }
            }
        }
    }

    public class WebBrowserD : WebBrowser
    {
        internal void Dispose(bool disposing)
        {
            // call WebBrower.Dispose(bool)
            base.Dispose(disposing);
        }
    }
}

This code can prevent Memory Leak.

In summary, You need just one class.

    public class WebBrowserD : WebBrowser
    {
        internal void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }
    }

Comments

  1. Di Stefano

    • 2019/5/23

    We are adversely affected by this memory leak with IE control inside The memory leak of WebBrowser is indeed a long-standing problem.

  2. Kase

    • 2016/12/16

    There is another post ( here : How to Fix the Memory Leak in IE WebBrowser Control? or How to get around the memory leak in the .NET Webbrowser control?) that suggests to call " SetProcessWorkingSetSize " from KERNEL32.DLL. The workaround is to minimize the winform of web-browser control.

  3. Saul

    • 2018/4/24

    Since we might or might not have control over the web page loaded in our Web Browser control based application, so for the web pages

  4. Elisha

    • 2020/6/29

    See this kb article from ms: http://support.microsoft.com/kb/893629[^] There is a memory leak if you add event handlers to any of the navigated elements. To fix, you'll have to keep a dictionary of all elements (include the top level document too), then in the OnDocumentCompleted ( ) function, remove the event handlers one by one while calling marshall.ReleaseComObject (o.DomDocument) in a loop, then finally

  5. Everett

    • 2016/11/4

    So the question should be rephrased to "How to Fix the Memory Leak in IE WebBrowser Control when IE7 is installed". Can anybody confirm that this problem is 

  6. Emerson

    • 2016/7/19

    Hi, I am building a C# application with an IE WebBrowser control in it. The Class that i am using is. System.Windows.Forms.WebBrowser m_WebBrowser.. Whenever a button is pressed in my application the WebBrowser form is loaded and the memory increases accordingly.

  7. Dupont

    • 2018/4/11

    So my question is: if there is another way to solve this problem? and if not, if I use an alternative web-browser control like mozilla-gecko I will solve this 

  8. Torres

    • 2016/3/31

    I tried to implement this in my vb.net scraper app - i call the following code before nevagition to a new page, with the hopes that it will fix the memory leaks of the previous page. code: Public Shared Sub Clean_JS(ByRef wb As System.Windows.Forms.WebBrowser) Dim args As Object() = {"document.body"}

  9. Kellan

    • 2016/6/27

    PB 12.6 application with an IE Web Browser control has what looks like a memory leak. It is unsure if the memory leak is coming from PowerBuilder or the IE 

  10. Joe

    • 2017/8/21

    The "memory leak" problem can be eliminated by using the Refresh () method instand of Navigate () method, followed by a GC.Collect (). The Code is in the following: Just declare the WebBrowser control using the "using" keyword. It will stop leaking memory when calling the Navigate () method anymore.

  11. Kyree

    • 2021/3/28

    A memory leak exists if the form is displayed as a modal dialog box. On closing the form, the WebBrowser control is not Net Framework 1.0, IE 6.0, VB.

  12. Eithan

    • 2016/6/4

    When reloading an angular application, via the browser reload, in IE 11 the browser's memory continually builds until it crashes. Expected behavior. On reload of the angular application in IE 11 the browser's memory will not build. Minimal reproduction of the problem with instructions. Run the demo plunker in IE11.

  13. Dominic

    • 2016/3/9

    I tried to create and add a webbrowser control on a form on runtime then later remove it on runtime to see if it will show some sign of 

  14. Aries

    • 2015/1/22

    From your post I can see that you've tried avoid the leak quite extensively and without success. I would suggest a different approach if feasible. Create a separate application that uses web browser control and start it from your application. Use the method described here to embed newly created application within your own existing application. Communicate with that application using WCF or .NET remoting.

  15. Kenneth

    • 2021/3/23

    2062.124 and here the problem doesn't occur (no slow-down or memory increase). I've seen mention of a memory leak in the .Net WebBrowser control 

Comments are closed.

Recent Posts