protected void Application_Start(object sender, EventArgs e) { WindowsEventLog.AddEvent("WebDav Application_Start()", 9999); IoCSetup.ForceLoad(typeof(EC.Core.Common.ForceLoad)); BootstrapContainer(); SetupServices(); }
/// <summary> /// Check if the parameter <c>obj</c> is <c>null</c>. If <c>obj</c> is <c>null</c>, /// write an error to the Windows Event Log. In a DEBUG build, an assertion failure /// will also cause the server to shut down. /// </summary> /// <param name="obj">Object to check.</param> /// <param name="message">Message for the log if the parameter <c>obj</c> is <c>null</c>.</param> /// <exception cref="AssertException">Throw exception if object is <c>null</c></exception> public static void NonNull <T>(T obj, string message) { if (obj != null) { return; } string msg = String.Format("{0} - Null check failure: {1}", DebugUtils.GetLocationFromStack(2), message); WindowsEventLog.AddEvent(msg, WindowsEventLog.DBCNonNull); ShutdownIfNeededAndThrow(msg); }
/// <summary> /// If the condition is false, log an error in the Windows Event Log. In a /// DEBUG build, an assertion failure will also cause the server to shut /// down. /// </summary> /// <param name="condition">Boolean to check</param> /// <param name="message">Message for event log</param> /// <exception cref="AssertException">Throw exception if assert fails (condition == <c>false</c>)</exception> public static void Assert(bool condition, string message) { if (condition) { return; } string msg = String.Format("{0} - Assertion Failure: {1}", DebugUtils.GetLocationFromStack(2), message); WindowsEventLog.AddEvent(msg, WindowsEventLog.DBCAssertion); ShutdownIfNeededAndThrow(msg); }
/// <summary> /// Initiates IOC /// </summary> /// <remarks> /// IoCSetupForceLoad() deals with the problem that the app is so loosely /// coupled that it won't bother loading some assemblies because it doesn't /// see direct references to this. /// </remarks> private void BootstrapContainer() { try { container = IoCSetup.Run("EC WebDav Application Starting", "EC-Web-Dav"); } catch (Exception ex) { var msg = String.Format("EC WebDav Application Startup (BootstrapContainer) - Unexpected Exception [{0}]", ex.Message.ToString()); WindowsEventLog.AddEvent(msg, WindowsEventLog.FatalError); } }
/// <summary> /// Shut down the application. This involves shutting down any background threads and then releasing the /// IoC container that was allocated in IoCSetup.Run(). /// </summary> public static void ShutdownThreadsAndReleaseContainer(string shutdownMsg) { if (ShuttingDown && Logger != null) { Logger.InfoFormat("IoCSetup::ShutdownThreadsAndReleaseContainer[{0}] - Re-entrant call. Stack = {1}", ContainerName, DebugUtils.GetStackTrace()); return; } ShuttingDown = true; if (Logger != null) { string msg = string.Format("IoCSetup::Shutdown[{0}] - {1}", ContainerName, shutdownMsg); Logger.Info(msg); } ShutdownBackgroundThreads(); MainContainer.Dispose(); WindowsEventLog.AddEvent(string.Format("IoCSetup::Shutdown[{0}] threads stopped and container disposed.", ContainerName), WindowsEventLog.Info); }
/// <summary> /// Initialize the Castle/Windsor IoC system. This includes setting up common facilities /// as well as registering components from all assemblies in the directory the application /// is executing from. /// </summary> /// <remarks> /// Originally this was called only once on application startup and a single container /// was used for the lifetime of the application. However, due to the way EF migration /// works, it became necessary to allocate new containers that would only be used in the /// context of EF migrations. These containers are assumed to be temporary in existence /// and it is also assumed that they should not have any background services /// associated with them. Thus, the suppressStartable parameter is interpreted to mean /// the caller is asking for a temporary-use container which has the effect /// both of suppressing the starting of IStartable components, but also of not storing /// the new container in the static member variable which is used to track the /// applications main container. /// </remarks> /// <remarks> /// RegisterCommonFacilities() must be called immediately on the newly created container /// because it sets up things like logging that we use every else. /// </remarks> /// <param name="startMsg">A startup message to place in the log</param> /// <returns>the initialized Windsor container</returns> public static IWindsorContainer Run(string startMsg, string containerName, bool suppressStartable = false) { WindowsEventLog.AddEvent(string.Format("IOCSetup.Run has been called for container name {0} (suppressStartable={1})", containerName, suppressStartable), WindowsEventLog.Info); ContainerName = containerName; var newContainer = new WindsorContainer(); newContainer.Kernel.ComponentCreated += Kernel_ComponentCreated; RegisterCommonFacilities(newContainer, suppressStartable); DBC.Assert(MainContainer == null, String.Format("IoCSetup::Run[{0}] - Duplicate main container", containerName)); MainContainer = newContainer; Logger = newContainer.Resolve <ILogger>(); Logger.Info(startMsg); DeactivatePropertyInjection(newContainer); SetupAssemblyLoadHook(); IList <Assembly> loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); loadedAssemblies.ForEach(a => LogAssemblyName(a, "initial")); RegisterAssembliesForIOC(newContainer, loadedAssemblies); return(newContainer); }
/// <summary> /// Shut down the IoC container and exit the application/process. This will also cause all /// component instances to be released and all startable components to be stopped. This call /// should never return because it causes the process to exit with <paramref name="exitCode"/> /// </summary> /// <remarks> /// <para> /// We call Environment.Exit() here because there are threads running which we don't have /// direct control over and which don't seem to get stopped when we dispose the container. /// For example, we have observed AsynAppender threads continuing to run after dispose on /// the container has returned. This probably shouldn't be the case, but it would be time /// consuming to track down why. If we don't exit here, then the process may not exit due /// to these running threads. /// </para> /// <para> /// We have to call Exit() in a separate thread because the SCM complains if you call /// Exit() on its thread (and when you stop a service via the SCM it is the SCM's thread /// that is calling into this code). /// </para> /// <para> /// There is an interesting deadlock scenario that ShutdownStoppables() needs to avoid. /// If the thread calling Shutdown() is the background thread for an object bearing the /// IBackgroundThread interface, and it tries to call Stop() on the instance for which it /// is a background thread, then a deadlock results (because it is trying to stop itself). /// So ShutdownStoppeables() needs to avoid this scenario. /// </para> /// <para> /// We should try to stop all incoming requests, and ensure that all in-process requests /// are complete prior to calling Dispose on the container. This is not implemented currently. /// </para> /// </remarks> /// <param name="shutdownMsg">The shutdown message to log before exiting.</param> /// <param name="exitCode">Exit code to stop the system (any code other than 0 for any error occurred).</param> public static void ShutdownAndExit(string shutdownMsg, int exitCode) { try { ShutdownThreadsAndReleaseContainer(shutdownMsg); if (exitCode != 0) { string msg = string.Format("IoCSetup::Shutdown[{0}] - {1} {2}", ContainerName, shutdownMsg, string.Format("Stack = {0}", DebugUtils.GetStackTrace())); WindowsEventLog.AddEvent(msg, WindowsEventLog.FatalError); } } catch (Exception ex) { var msg = String.Format("IoCSetup::Shutdown[{0}]: Unexpected exception Msg={1} Ex = {2}", ContainerName, shutdownMsg, ex); WindowsEventLog.AddEvent(msg, WindowsEventLog.FatalError); } Task.Factory.StartNew(() => Environment.Exit(exitCode)); }
protected void Application_Error(object sender, EventArgs e) { //Log the Error Exception ex = Server.GetLastError(); ILogger logger = null; try { if (ex != null) { string errMsg = string.Format("Unhandled top-level error: {0}", ex.ToString()); string innerErrMsg = ex.InnerException != null?string.Format("Unhandled top-level error (inner): {0}", ex.InnerException.Message) : "No inner exception"; // Event logs... WindowsEventLog.AddEvent(string.Format("WebDav Global.Application_Error(): {0}", errMsg), 9999); if (ex.InnerException != null) { WindowsEventLog.AddEvent(string.Format("WebDav Global.Application_Error(): {0}", innerErrMsg), 9999); } // File log... logger = container.Resolve <ILogger>(); logger.Error(errMsg); if (ex.InnerException != null) { logger.ErrorFormat("WebDav Global.Application_Error(): {0}", innerErrMsg); } } else { WindowsEventLog.AddEvent("WebDav Global.Application_Error(): No exception found", 9999); } } finally { if (logger != null) { container.Release(logger); } } }
protected void Application_End(object sender, EventArgs e) { WindowsEventLog.AddEvent("WebDav Application_End()", 9999); }