Proposed Memory Leak in IE WebBrowser Control

  • 2008년 11월 14일 금요일 오후 9:04
     
     
    Ok, I hope this is the correct place to ask this question!

    I originally asked this question in the C# Development forum:
    http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=8&SiteID=1
    but one of the moderators informed me that I needed to ask it in the
    IE Discussion Group
    but one of the moderators there told me that I need to ask it in THIS forum!
    Here is my question:

    This appears to be a common problem, but so far I have not found any answers
    to it.

    I am building a C# application with an IE WebBrowser control in it.
    Whenever I navigate within a page I've loaded in the control, large amounts
    of memory are being used and not released. After 7 hours of use, my app was
    showing a memory use of 900MB, which is simply unacceptable for my clients.

    My question (for myself and all the others who have asked it) is: how can we
    release the memory being used by the WebBrowser control without completely
    shutting down the application? I have tried removing the WebBrowser control
    from it's parent form and calling the dispose() Method on it, but the memory
    is not released. I have confirmed the memory leak/usage with Taskmgr.exe,
    Perfmon.exe, and Process Explorer, all of which show this abnormally high
    memory usage.

    I understand that the memory usage might come in part from circular
    references in the underlying DOM object, but I need a way to manually free
    this memory from time to time.

    If this is in no way possible, then what alternatives do developers have
    (seeing as this memory consumption is not acceptable to many of us)?

    I would really appreciate it, and think it would be great if we can finally
    resolve this issue! Thank you so much for your assistance!

    Again, I apologize if this is the wrong forum, but I was informed
    that this was the place to post this!  Thanks again!

모든 응답

  • 2008년 11월 14일 금요일 오후 10:54
     
     
    What I do is to spawn off a web browser automating program, passing an id via command line. The program reads additional request information from a database based on the id and writes automating result to the database row identified by the id, then exits. 
  • 2008년 11월 17일 월요일 오전 5:42
     
     
    I'm not quite sure how this answers my question.  I'm probably just missing something; sorry!
  • 2008년 11월 17일 월요일 오후 3:27
     
     
    Aren't you asking for alternatives?
  • 2008년 11월 18일 화요일 오후 11:22
     
     
    Ok, I understand what you are saying now; thank you for the suggestion!  However, if many operations are being done on a particular HTML document at regular intervals, it isn't very practical for me to spawn new apps constantly.

    If there is no way to deal with the memory leak in the IE control, I am looking for alternatives to the IE WebBrowser control itself.

    Thanks in advance for your help!
  • 2008년 11월 19일 수요일 오후 12:20
     
     

    You will thank me for ever for this solution -

    I had couple of application using web browser control and these windows would contineously load new pages. Every time new page loads the application will consume about 5mb memory and would never release it. That would cause the the meory use to go above 1.5 gb in short time causing the application to run slow and finally crash just after couple hours.

    The culprit is IE7. It had severe memory leak issues.

    Solution - Install new browser IE8. All memory leaks plugged. application do not consume any more memory, runs smoothly for hours without crashing Smile

     

    Ajit

     

  • 2008년 11월 26일 수요일 오전 5:45
     
     

     

    You can try to navigate to about:blank and next back to the page. In my case a memory ocupied by the IE control will be freed.
  • 2008년 11월 30일 일요일 오전 8:25
     
     
    Thank you both for the suggestions!  Unfortunately, I am still in the same position; memory is being consumed and never released.  I have updated to IE8 and tried navigating to an about:blank page to no avail.
  • 2008년 12월 3일 수요일 오후 3:45
     
     제안된 답변

    Is the memory released when you minimize the app ?
    If so, try this:

    -- 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);


    • 답변으로 제안됨 studysake 2011년 8월 15일 월요일 오전 6:31
    •  
  • 2009년 1월 4일 일요일 오후 5:42
     
     
     I've got the same issue and have for a long time.  After the web browser control is used for a while the memory keeps growing and never releases.  Collecting the garbage doesn't work, things are disposed of properly, minimizing the window doesn't work.. the only thing that fixes it is to restart the application.  It will continue to grow until the application crashes.  I haven't found any solutions for this as of yet. 
  • 2009년 1월 22일 목요일 오후 7:56
     
     
    I am having the same issue and I haven't been able to find a solution anywhere. Could be that the WebBrowser control is just cursed to be a memory leaking hog. =( Has anyone found a solution or an alternative control based on another browser?

    Thanks in advance...

    Gnom3
  • 2009년 1월 28일 수요일 오후 9:24
     
     

    I have the same problem, I try to do everything but VM / Memory Size keeping growing

    wb .Dispose();

    wb = null;

    GC.Collect();

    GC.WaitForPendingFinalizers();

    GC.Collect();

    Can someone please give us a hint to solve the problem.

  • 2009년 2월 11일 수요일 오전 10:14
     
     
    Hello,

    I have this problem too.
    try this page : http://support.microsoft.com/kb/896663
    or this page too : http://support.microsoft.com/kb/943510/
    may be can help you.

    best regards


  • 2009년 3월 16일 월요일 오후 10:02
     
     
    I can't believe there's no solution to this browser control memory leak issue.  I'm having the same problem and have found no solutions online.  The only choice is to restart the entire process every so often.  Which is soooo 1990's.

    I tried all the GC techniques, which doesn't do anything for the unmanaged memory leak coming from the underlying ActiveX component.  Also tried creating AppDomains to host the browser control.  AppDomains don't seem to separate out the unmanaged memory.  They all share the same pool, which when exited, leaves the leaked memory unchanged.  

    Ugghhhhhhh.  This is way dumb.

    Anyone else have any suggestions?
  • 2009년 4월 2일 목요일 오후 10:03
     
     제안된 답변
    This solution worked for me!!
    Thank you so much mike_t2e!!!!!!!

    -----------------------------------------------------------------------

    Is the memory released when you minimize the app ?
    If so, try this:

    -- 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);
    • 답변으로 제안됨 zwars 2009년 6월 11일 목요일 오전 10:24
    •  
  • 2009년 5월 25일 월요일 오후 12:43
     
     
    Thanks, mike_t2e!  Your solution helped me very much!
    • 편집됨 ept01 2009년 5월 25일 월요일 오후 12:44
    •  
  • 2009년 5월 25일 월요일 오후 4:01
     
     
    SetProcessWorkingSetSize doesn't actually release any memory. It does incease the probabilty of the memory being paged out to disk, and probably cause a GC collect.
    Memory leaks like circular reference of javascript objects may not be affected though. Until IE7, IE does not break circular reference automatically.

    MSMVP VC++
  • 2009년 10월 15일 목요일 오후 5:47
     
     
    Please DO NOT use script manager and update panel , they have memory leak
  • 2010년 5월 30일 일요일 오전 10:43
     
     
    SetProcessWorkingSetSize doesn't actually release any memory. It does incease the probabilty of the memory being paged out to disk, and probably cause a GC collect.
    Memory leaks like circular reference of javascript objects may not be affected though. Until IE7, IE does not break circular reference automatically.

    MSMVP VC++

    This is true... SetProcessWorkingSetSize doesn't release any memory.
    I don't understand background workings of WebBrowser control, but I realised one thing:
    My program goes through 500 or more pages and reads new content on them. It hogs the RAM quite quickly, and if I run the same function that runs through all those pages again, it simply reads from webbrowser cache, cause it needs only couple of seconds to complete.
    It means that we only need to clear browser cache in order to free RAM. Right? I found this solution, but it doesn't work.

    http://support.microsoft.com/kb/326201/en-us

    It allways gives me PrtectedMemoryException..
    Ok, so how is it possible that the memory is freed only when I close my application, and it's not freed when i dispose my webbrowser control and create new one?
  • 2010년 5월 30일 일요일 오후 4:05
     
     
    Dispose isn't necessary freeing memory. It merely tells the COM server you do not hold the object anymore. The COM server is free to decide when to free memory (e.g. when gc collect or cache expire or wininet session clear)

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
  • 2010년 5월 31일 월요일 오후 2:58
     
     
    (reposted here, edited)

    I still have the problem having tried all the fixes here - including using subtasks. Web pages are now becoming so loaded with script the granularity of individual subtasks is becoming an issue. On at least two critical sites memory consumption is so dire I need a better fix. Bad sites can leak around 1Mb per page so after ~2000 pages a 32-bit process is consuming >2Gb and fails.

    Switching off script cures the leaks but breaks some sites. IE8 still has the problem despite the fixes here:
      http://msdn.microsoft.com/en-us/library/dd361842%28VS.85%29.aspx
    In some cases I may be able to change the site script. Does anyone have similar examples of what the site authors should still avoid?

    Is there anything else I can try?

    Will IE9 make further improvements to garbage collection? Might this fix the issue or should I assume not?

    Thanks!
    R.


  • 2010년 7월 5일 월요일 오후 3:34
     
      코드 있음

    Same here. It became even worse with IE7 and IE8. I found out that the Solution with something like:

    SetProcessWorkingSetSize(pi.hProcess, (SIZE_T)-1, (SIZE_T)-1))

    does it for a while, when I do it every 20 navigations.

    Then when the Pagefile-Usage is above a certain limit the application is restarted completely rather fast, so it is freed again.

    Sad story is, that it is in an MFC-CHtmlView, already filled with correction-code from a dozen KB's and the whole app is many years old.

    I hope this horror is soon being solved, on the long run it is getting embarassing to sell software that is based on CHtmlView or WebBrowser2. I got the same problems with doing it with WTL/ATL. After an intensive debugging it is provable, that it happens in Navigate/Navigate2.

    If there is any solution: please, please, please!

  • 2010년 7월 15일 목요일 오후 3:16
     
     

    We are now 15 07 2010 . Is there already a solution for this problem?

    This bug prevents developers to make a professional application with this control.

    It's so strange Microsoft can't find an aswser for this?

    Peter Adriaenssens

     

     

  • 2010년 7월 17일 토요일 오전 3:29
     
     
    I met this problem also, and I found that if I minimize the window, the memory will decrease immediately. So I periodically minimize the dialog.
  • 2010년 8월 13일 금요일 오전 9:24
     
      코드 있음
    That is the same like
    SetProcessWorkingSetSize(pi.hProcess, (SIZE_T)-1, (SIZE_T)-1))
    

    and it also only works correctly on Windows without DirectX-Desktop (pre-vista/7).

    In the meantime we redeveloped the thing with OLE/COM in pure platform-sdk-windows-C-code and removed any framework around. Strangely now it works and doesn't leak anymore. I assume now it is inside MFC and WTL where the wrappers are initialized or the surrounding code for Navigate(2) is called.

    This whole thing is like proving the Fermat-equations :-) Seems like it goes over years and years.

  • 2011년 1월 5일 수요일 오후 3:43
     
     제안된 답변

    There is a known memory leak in the WebBrowser control.  See the following Microsoft KB article - KB893629

    Hope this helps!  If you find this post as helpful, please mark it as such.


    If this post is helpful, please mark it as such!
    Dave Black, MCPD, MCTS
    http://dave-black.blogspot.com

    • 편집됨 Dave Black 2011년 1월 5일 수요일 오후 3:45 remove duplicate text
    • 답변으로 제안됨 Dave Black 2011년 3월 14일 월요일 오후 2:11
    •  
  • 2011년 5월 10일 화요일 오후 8:47
     
      코드 있음
        public void SetSelectedCorridor(string value)
        {
          JavaScriptFun("SelectStationList", value);
          JavaScriptFun("SetStationOption", value);
        }
    
        public object JavaScriptFun(string funName, params object[] args)
        {
          return bFT.Document.InvokeScript(funName, args);
        }
    

    After calling SetSelectedCorridor, the WebBrowser control leaks memory at a rate of about 1 KB/sec.

    The same thing happens when I use an option list input on the page that calls "SelectStationList" when the selected option changes.
    This problem does not happen when the page is loaded in IE 8.

    I have XP service pack 3 so I don't think the KB893629 applies. SP3 applies this patch.

    The one workaround I have found that works is to call webBrowser1.Stop(); after my JavaScript is runs. I invoke a timer handler to run Stop so that
    the page refresh has time to complete before the Stop is called.

    Any idea why my scripts start a constant slow memory leak when running in the WebBrowser control?

  • 2011년 5월 13일 금요일 오후 2:34
     
     

    I am a little bit new here, but already found a lot of help.

    And also in this post, thanks, thanks!


    IE Prof
    Martijn de Ruiter
    http://www.dehorecaopkoper.nl

  • 2011년 6월 27일 월요일 오전 4:21
     
     

    June 2011, IE 9 installed. Still having the problem. 

    Yeahhhhhhhhhhhhhhhhhhhh!

  • 2011년 6월 30일 목요일 오후 4:01
     
     

    Thank you very much, this solution work OK in my app.

     

  • 2011년 8월 15일 월요일 오전 6:32
     
     
    This worked for me mike_t2e. Thanks for your solution.
  • 2012년 1월 4일 수요일 오후 4:25
     
     
    mike_t2e thanks very much that does seem to clear away some of the cruft.

    As other have indicated it's not a complete solutions but stymies the tide a little.

    I suppose I will have to consider Shengs workarounds in the long term....

    This issue has been on the card for Years and Years now... Ah well.

    Thank for the little help. it helped.

    I came, I saw, I coded
  • 2012년 2월 27일 월요일 오후 10:38
     
     

    Depending on a person's particular machine, I believe there are two separate issues going on here. First, as several people pointed out, there is a known memory leak in IE7. However, I am running IE8 on Windows 7 64-bit and notice similar but different behavior.

    In my case, when I close my application that has the WebBrowser control, the memory does get released. By definition, a memory leak can't get released without actually rebooting your computer. So the similar phenomenon that is happening with newer versions of IE is not a memory leak. Rather, I would point the finger at .NET's black box garbage collector for being too slow and not recognizing when memory can be release.

    I've read a number of posts that suggest a range of success/failure in using manual calls to GC to release memory. I'm still looking into this. But my main point was not to assume its a memory leak just because huge chunks of memory are getting used up. First check to see if that memory gets released when you shut down your application.

  • 2012년 2월 29일 수요일 오후 3:08
     
     

    In my case, when I close my application that has the WebBrowser control, the memory does get released. By definition, a memory leak can't get released without actually rebooting your computer. So the similar phenomenon that is happening with newer versions of IE is not a memory leak. Rather, I would point the finger at .NET's black box garbage collector for being too slow and not recognizing when memory can be release.

    That must belong somewhere else.

    1) We are talking about native, non-.NET- Applications here.

    2) Assuming a windows-platform that can run IE7/IE8: A memory-leakage that is occuring in the storage-region belonging to a certain process is also gone, when that process is gone. Proof that such stuff applies to IWebBrowser2-related things is here: IWebBrowser2's memory not deallocated

    I still think it is in MFC/WTL, because after rewriting the application, so that it NOT uses it, we didn't have the effect anymore.

  • 2012년 3월 6일 화요일 오전 12:41
     
     

    I had luck with mikes solution coupled with a deconstruction of the controls and disposal of the control before the form is disposed:

    //main form

    bool firstTime = true;

                //to test memory leak in a loop create my flash video player embedded in a web browser control on a winform
                while (firstTime || chkContinuousTesting.Checked) {
                    firstTime = false;


                    string fileName = @"C:\Personal\MPV\TestVideo\Videos\20051210-w50s.flv";
                    FormVideoPlayer frm = new FormVideoPlayer();
                    frm.Play(fileName);
                    frm.ShowDialog(this);
                    frm.Dispose();
                    frm = null;


                    //cleanup to take care of WebBrowser memory leak
                    Win32.MinimizeRelease();
                }

    //on close event from video player form

    private void FormVideoPlayer_FormClosing(object sender, FormClosingEventArgs e) {

                this.Hide();


                //help to clean up web browser memory leak
                webBrowser1.Stop();


                this.SuspendLayout();

                webBrowser1.PreviewKeyDown -= new System.Windows.Forms.PreviewKeyDownEventHandler(this.webBrowser1_PreviewKeyDown); //unregister any events to prevent memory leak
                this.Controls.Remove(this.webBrowser1); //remove the control
                this.ResumeLayout(false);


                webBrowser1.Dispose(); //dispose the control
                webBrowser1 = null;            
            }

    //Win32 Class

    using System;             //Required for Win32Exception
    using System.Runtime.InteropServices;    //Required for DllImport, IntPtr ...
    using System.ComponentModel;


    namespace TestVideo {
        public class Win32 {

    #region Minimize, Memory Release

            [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();


            public static void MinimizeRelease() {
                IntPtr pHandle = GetCurrentProcess();
                SetProcessWorkingSetSize(pHandle, -1, -1);


                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();

          }
            #endregion
        }
    }

    After this fix I ran for many hours without seeing any memory increasing.

    Jason


  • 2012년 9월 29일 토요일 오전 10:49
     
     

    It is sad to see that there is no working solution yet to this issue.

    Seems that nobody from Microsoft bothered to create a fix for this control.

    Has anyone tried other controls as alternatives in a commercial application.

    Maybe:

    http://code.google.com/p/geckofx/

    http://webkitdotnet.sourceforge.net/

    http://awesomiumdotnet.codeplex.com/

    http://code.google.com/p/open-webkit-sharp/

    Any thoughts?

    Thx,

    Daniel



    -Creator-

  • 2012년 10월 8일 월요일 오전 9:23
     
     

    Has anyone tried any of those WebBrowser components?

    IE webBrowser is useless for my purpose, hoping someone would light my path with an alternative.

    Daniel


    -Creator-

  • 2012년 12월 18일 화요일 오후 5:36
     
     

    o_O

    Mike! its Works, very impressive.

    I'm working on an application that uses a webbrowser, I have several tabs in the main html, and whenever sailing including memory increased.

    Now by using this code between the navigation memory is freed.

    Very very thanks!


    SifriG

  • 2013년 2월 4일 월요일 오후 2:52
     
     

    Daniel:

    As I wrote before, you can use the IWebbrowser2 directly, without a framework. This might be taking some time and for my case I had to rewrite the whole applications GUI. But ... It worked.

    BTW: I retested the problem with the MFC GUI in CHtmlView with VC11 and it still occurs.