Monday, 26 April 2010

Disabling File Change Notification (FCN) to avoid AppDomain restarting when adding a directory

I found this code here, and it works a treat. Drop it into your Global.asax (Application_Start) and it will prevent your AppDomain restarting when a subdirectory is modified/added/deleted.

This problem reared its ugly for me recently when logged-in users were losing their sessions because of activities elsewhere on the same system that were creating directories. Problem solved!

//FIX disable AppDomain restart when deleting subdirectory

//This code will turn off monitoring from the root website directory.

//Monitoring of Bin, App_Themes and other folders will still be operational, so updated DLLs will still auto deploy.

System.Reflection.PropertyInfo p = typeof(System.Web.HttpRuntime).GetProperty("FileChangesMonitor", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);

object o = p.GetValue(null, null);

System.Reflection.FieldInfo f = o.GetType().GetField("_dirMonSubdirs", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.IgnoreCase);

object monitor = f.GetValue(o);

System.Reflection.MethodInfo m = monitor.GetType().GetMethod("StopMonitoring", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); m.Invoke(monitor, new object[] { }); 

4 comments:

  1. This code was working beautifully for me, but not anymore.

    Windows 7 64bit. Am using VS 2010, VB.net and am running the project using the VS 2010 local webserver, have not yet tried in on IIS 7.5/Windows Server 2008.

    Stopped working for me after:

    Upgraded to the latest AjaxControlToolkit (June 2013)
    Installed VS 2012 (but still using VS 2010)
    Installed .NET Framework 4.5 (but still targeting 4.0 in my application)

    I am allowing users to upload images into directories/sub-directories inside the application root. Sub-directories are created and deleted, image files are added and deleted during the session.

    I was having session loss when performing these operations until I found the above code. When I put it into Application_Start (Global.asax) it solved the problem perfectly.

    With the above changes to my system, the above code no longer works and I am back to losing my session upon any modifications to these sub-directories.

    I could switch to a model where these directories are outside of the application root, but I am displaying images inside GridView controls that require URLs (ex: ~\Images\TempUploadedFiles), not absolute paths.

    I would really like to know what I need to do or change to get the above code working again.

    Has anyone else had this experience?

    Thanks

    ReplyDelete
  2. Looks like I found a solution (see above post)...

    I found an alternate version of the original code posted above.

    For whatever reason, the differences in the following code (VB.NET) work for me, while the previous code had stopped working (after the changes to my system, mentioned in the previous post).

    Just drop the following code into an existing class or create a new one. You will need to add "Imports System.Reflection" (or C# equivalent) at the beginning of the class. I converted this code from C# to VB.Net using a code converter on the web.

    Friend NotInheritable Class HttpInternals
    Private Sub New()
    End Sub
    Private Shared ReadOnly s_TheRuntime As FieldInfo = GetType(HttpRuntime).GetField("_theRuntime", BindingFlags.NonPublic Or BindingFlags.[Static])

    Private Shared ReadOnly s_FileChangesMonitor As FieldInfo = GetType(HttpRuntime).GetField("_fcm", BindingFlags.NonPublic Or BindingFlags.Instance)
    Private Shared ReadOnly s_FileChangesMonitorStop As MethodInfo = s_FileChangesMonitor.FieldType.GetMethod("Stop", BindingFlags.NonPublic Or BindingFlags.Instance)

    Private Shared ReadOnly Property HttpRuntime() As Object
    Get
    Return s_TheRuntime.GetValue(Nothing)
    End Get
    End Property

    Private Shared ReadOnly Property FileChangesMonitor() As Object
    Get
    Return s_FileChangesMonitor.GetValue(HttpRuntime)
    End Get
    End Property

    Public Shared Sub StopFileMonitoring()
    s_FileChangesMonitorStop.Invoke(FileChangesMonitor, Nothing)
    End Sub
    End Class

    Then in your Application_Start method (in Global.asax), add this line of code:

    HttpInternals.StopFileMonitoring()

    This allowed me to once again, manipulate (add, delete) files/directories inside my application root without losing my session.

    The original code I believe, allowed changes to web.config to be detected and just disabled monitoring to sub-directories, which is desirable, so I am not sure if this code possibly disables all file monitoring within the application root.

    ReplyDelete
  3. Thanks for the update Thomas!

    ReplyDelete

Comments are moderated, so you'll have to wait a little bit before they appear!