File: System\Windows\Application.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
//
//
// Description:
//              The Application object is a global object that the Avalon platform
//              uses to identify, reference, and communicate with an Avalon application.
//
//              The application object also presents a consistent logical view of an application
//              to an Avalon developer.
//              An Avalon developer uses the application object to listen and respond to application-wide
//              events (like startup, shutdown, and navigation events),
//              to define global properties and maintain state across multiple pages of markup.
//
 
 
//In order to avoid generating warnings about unknown message numbers and unknown pragmas
//when compiling your C# source code with the actual C# compiler, you need to disable
//warnings 1634 and 1691. (From PreSharp Documentation)
#pragma warning disable 1634, 1691
 
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Threading;
 
using System.IO.Packaging;
using System.Windows.Threading;
using System.Windows.Navigation;
using System.Windows.Interop;
using System.Windows.Resources;
using System.Windows.Markup;
using System.Net;
 
using MS.Internal;
using MS.Internal.AppModel;
using MS.Internal.IO.Packaging;
using MS.Internal.Interop;
using MS.Internal.Utility;
using MS.Utility;
using MS.Win32;
using Microsoft.Win32;
using MS.Internal.Telemetry.PresentationFramework;
using System.Diagnostics.CodeAnalysis;
 
using PackUriHelper = System.IO.Packaging.PackUriHelper;
 
namespace System.Windows
{
    /// <summary>
    /// Delegate for Startup Event
    /// </summary>
    public delegate void StartupEventHandler(Object sender, StartupEventArgs e);
 
    /// <summary>
    /// Delegate for the Exit event.
    /// </summary>
    public delegate void ExitEventHandler(Object sender, ExitEventArgs e);
 
    /// <summary>
    /// Delegate for SessionEnding event
    /// </summary>
    public delegate void SessionEndingCancelEventHandler(Object sender, SessionEndingCancelEventArgs e);
 
    #region Application Class
 
    /// <summary>
    /// Application base class
    /// </summary>
    public class Application : DispatcherObject, IHaveResources, IQueryAmbient
    {
        //------------------------------------------------------
        //
        //  Constructors
        //
        //------------------------------------------------------
 
        #region Constructors
        /// <summary>
        /// The static constructor calls ApplicationInit
        /// </summary>
        static Application()
        {
            ApplicationInit();
        }
 
        /// <summary>
        ///     Application constructor
        /// </summary>
        public Application()
        {
#if DEBUG_CLR_MEM
            if (CLRProfilerControl.ProcessIsUnderCLRProfiler &&
               (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
            {
                CLRProfilerControl.CLRLogWriteLine("Application_Ctor");
            }
#endif // DEBUG_CLR_MEM
 
            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordGeneral | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientAppCtor);
 
            lock(_globalLock)
            {
                // set the default statics
                // DO NOT move this from the begining of this constructor
                if (_appCreatedInThisAppDomain == false)
                {
                    Debug.Assert(_appInstance == null, "_appInstance must be null here.");
                    _appInstance = this;
                    IsShuttingDown    = false;
                    _appCreatedInThisAppDomain = true;
                }
                else
                {
                    //lock will be released, so no worries about throwing an exception inside the lock
                    throw new InvalidOperationException(SR.MultiSingleton);
                }
            }
 
 
            //
            // (Application not shutting down when calling
            // Application.Current.Shutdown())
            //
            // post item to do startup work
            // posting it here so that this is the first item in the queue. Devs
            // could post items before calling run and then those will be serviced
            // before if we don't post this one here.
            //
            // Also, doing startup (firing OnStartup etc.) once our dispatcher
            // is run ensures that we run before any external code is run in the
            // application's Dispatcher.
            Dispatcher.BeginInvoke(
                DispatcherPriority.Send,
                (DispatcherOperationCallback) delegate(object unused)
                {
                    // Shutdown may be started before the Dispatcher gets to this callback.
                    // This can happen in browser-hosted applications.
                    if (IsShuttingDown)
                        return null;
 
                    // Event handler exception continuality: if exception occurs in Startup event handler,
                    // our state would not be corrupted because it is fired by posting the item in the queue.
                    // Please check Event handler exception continuality if the logic changes.
                    StartupEventArgs e = new StartupEventArgs();
                    OnStartup(e);
 
                    // PerformDefaultAction is used to cancel the default navigation for the case
                    // when the app is being loaded as a result of a history navigation.  In such
                    // a case, we don't want to show the startupUri page, rather we show the last
                    // page of the app that we in use before navigating away from it.
                    if (e.PerformDefaultAction)
                    {
                        DoStartup();
                    }
                    return null;
                },
                null);
        }
        #endregion Constructors
 
        //------------------------------------------------------
        //
        //  Public Methods
        //
        //------------------------------------------------------
 
        #region Public Methods
 
        ///<summary>
        ///     Run is called to start an application.
        ///
        ///     Typically a developer will do some setting of properties/attaching to events after instantiating an application object,
        ///     and then call Run() to start the application.
        ///</summary>
        ///<remarks>
        ///     Once run has been called - an application's OnStartup override and Startup event is called
        ///     immediately afterwards.
        ///</remarks>
        /// <returns>ExitCode of the application</returns>
        public int Run()
        {
            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordGeneral | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientAppRun);
            return this.Run(null);
        }
 
        ///<summary>
        ///     Run is called to start an application.
        ///
        ///     Typically a developer will do some setting of properties/attaching to events after instantiating an application object,
        ///     and then call Run() to start the application.
        ///     Any arguments passed in as a string array will be added to the command Line property of the StartupEventArgs property.
        ///     The exit code returned by Run will typically be returned to the OS as a return value.
        ///</summary>
        ///<remarks>
        ///     Once run has been called - an application's OnStartup override and Startup event is called
        ///     immediately afterwards.
        ///</remarks>
        /// <param name="window">Window that will be added to the Windows property and made the MainWindow of the Applcation.
        /// The passed Window must be created on the same thread as the Application object.  Furthermore, this Window is
        /// shown once the Application is run.</param>
        /// <returns>ExitCode of the application</returns>
        public int Run(Window window)
        {
            VerifyAccess();
            return RunInternal(window);
        }
 
 
        /// <summary>
        ///
        /// </summary>
        /// <param name="serviceType"></param>
        /// <returns></returns>
        internal object GetService(Type serviceType)
        {
            // this is called only from OleCmdHelper and it gets
            // service for IBrowserCallbackServices which is internal.
            // This call is made on the App thread.
            //
            VerifyAccess();
            object service = null;
 
            if (ServiceProvider != null)
            {
                service = ServiceProvider.GetService(serviceType);
            }
            return service;
        }
 
        /// <summary>
        ///     Shutdown is called to programmatically shutdown an application.
        ///
        ///     Once shutdown() is called, the application gets called with the
        ///     OnShutdown method to raise the Shutdown event.
        ///     Requires SecurityPermission for unmanaged code
        /// </summary>
        /// <remarks>
        ///     Requires UIPermission with AllWindows access
        /// </remarks>
        public void Shutdown()
        {
            Shutdown(0);
        }
 
        /// <summary>
        ///     Shutdown is called to programmatically shutdown an application.
        ///
        ///     Once shutdown() is called, the application gets called with the
        ///     OnShutdown method to raise the Shutdown event.
        ///     The exitCode parameter passed in at Shutdown will be returned as a
        ///     return parameter on the run() method, so it can be passed back to the OS.
        /// </summary>
        /// <remarks>
        ///     Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
        /// </remarks>
        /// <param name="exitCode">returned to the Application.Run() method. Typically this will be returned to the OS</param>
        public void Shutdown(int exitCode)
        {
            CriticalShutdown(exitCode);
        }
        internal void CriticalShutdown(int exitCode)
        {
            VerifyAccess();
            //Already called once??
            if (IsShuttingDown == true)
            {
                return;
            }
 
            ControlsTraceLogger.LogUsedControlsDetails();
 
            SetExitCode(exitCode);
            IsShuttingDown = true;
            Dispatcher.BeginInvoke(DispatcherPriority.Normal, new DispatcherOperationCallback(ShutdownCallback), null);
}
 
        /// <summary>
        ///     Searches for a resource with the passed resourceKey and returns it
        /// </summary>
        /// <remarks>
        ///     If the sources is not found on the App, SystemResources are searched.
        /// </remarks>
        /// <param name="resourceKey">Name of the resource</param>
        /// <returns>The found resource.</returns>
        /// <exception cref="ResourceReferenceKeyNotFoundException"> if the key is not found.</exception>
        public object FindResource(object resourceKey)
        {
            ResourceDictionary resources = _resources;
            object resource = null;
 
            if (resources != null)
            {
                resource = resources[resourceKey];
            }
 
            if (resource == DependencyProperty.UnsetValue  || resource == null)
            {
                // This is the top of the tree, try the system resource collection
                // Safe from multithreading issues, SystemResources uses the SyncRoot lock to access the resource
                resource = SystemResources.FindResourceInternal(resourceKey);
            }
 
            if (resource == null)
            {
                Helper.ResourceFailureThrow(resourceKey);
            }
 
            return resource;
        }
 
        /// <summary>
        ///     Searches for a resource with the passed resourceKey and returns it
        /// </summary>
        /// <remarks>
        ///     If the sources is not found on the App, SystemResources are searched.
        /// </remarks>
        /// <param name="resourceKey">Name of the resource</param>
        /// <returns>The found resource.  Null if not found.</returns>
        public object TryFindResource(object resourceKey)
        {
            ResourceDictionary resources = _resources;
            object resource = null;
 
            if (resources != null)
            {
                resource = resources[resourceKey];
            }
 
            if (resource == DependencyProperty.UnsetValue  || resource == null)
            {
                // This is the top of the tree, try the system resource collection
                // Safe from multithreading issues, SystemResources uses the SyncRoot lock to access the resource
                resource = SystemResources.FindResourceInternal(resourceKey);
            }
            return resource;
        }
 
        //
        // Internal routine only look up in application resources
        //
        internal object FindResourceInternal(object resourceKey)
        {
            // Call Forwarded
            return FindResourceInternal(resourceKey, false /*allowDeferredResourceReference*/, false /*mustReturnDeferredResourceReference*/);
        }
 
        internal object FindResourceInternal(object resourceKey, bool allowDeferredResourceReference, bool mustReturnDeferredResourceReference)
        {
            ResourceDictionary resources = _resources;
 
            if (resources == null)
            {
                return null;
            }
            else
            {
                bool canCache;
                return resources.FetchResource(resourceKey, allowDeferredResourceReference, mustReturnDeferredResourceReference, out canCache);
            }
        }
 
        /// <summary>
        /// Create logic tree from given resource Locator, and associate this
        /// tree with the given component.
        /// </summary>
        /// <param name="component">Root Element</param>
        /// <param name="resourceLocator">Resource Locator</param>
        public static void LoadComponent(Object component, Uri resourceLocator)
        {
            ArgumentNullException.ThrowIfNull(component);
            ArgumentNullException.ThrowIfNull(resourceLocator);
 
            if (resourceLocator.OriginalString == null)
                throw new ArgumentException(SR.Format(SR.ArgumentPropertyMustNotBeNull,"resourceLocator", "OriginalString"));
 
            if (resourceLocator.IsAbsoluteUri == true)
                throw new ArgumentException(SR.AbsoluteUriNotAllowed);
 
            // Passed a relative Uri here.
            // needs to resolve it to Pack://Application.
            //..\..\ in the relative Uri will get stripped when creating the new Uri and resolving to the
            //PackAppBaseUri, i.e. only relative Uri within the appbase are created here
            Uri currentUri = new Uri(BaseUriHelper.PackAppBaseUri, resourceLocator);
 
            //
            // Generate the ParserContext from packUri
            //
            ParserContext pc = new ParserContext();
 
            pc.BaseUri = currentUri;
 
            bool bCloseStream = true;  // Whether or not to close the stream after LoadBaml is done.
 
            Stream stream = null;  // stream could be extracted from the manifest resource or cached in the
                                   // LoadBamlSyncInfo depends on how this method is called.
 
            //
            // We could be here because of an InitializeCompoenent() call from the ctor of this component.
            // Check if this component was originally being created from the same Uri by the BamlConverter
            // or LoadComponent(uri).
            //
            if (IsComponentBeingLoadedFromOuterLoadBaml(currentUri) == true)
            {
                NestedBamlLoadInfo nestedBamlLoadInfo = s_NestedBamlLoadInfo.Peek();
 
                // If so, use the stream already created for this component on this thread by the
                // BamlConverter and seek to origin. This gives better perf by avoiding a duplicate
                // WebRequest.
                stream = nestedBamlLoadInfo.BamlStream;
 
                stream.Seek(0, SeekOrigin.Begin);
 
                pc.SkipJournaledProperties = nestedBamlLoadInfo.SkipJournaledProperties;
 
                // Reset the OuterUri in the top LoadBamlSyncInfo in the stack for the performance optimization.
                nestedBamlLoadInfo.BamlUri = null;
 
                // Start a new load context for this component to allow it to initialize normally via
                // its InitializeComponent() so that code in the ctor following it can access the content.
                // This call will not close the stream since it is owned by the load context created by
                // the BamlConverter and will be closed from that context after this function returns.
 
                bCloseStream = false;
            }
            else
            {
                // if not, this is a first time regular load of the component.
                PackagePart part = GetResourceOrContentPart(resourceLocator);
                ContentType contentType = new ContentType(part.ContentType);
                stream = part.GetSeekableStream();
                bCloseStream = true;
 
                //
                // The stream must be a BAML stream.
                // check the content type.
                //
                if (!MimeTypeMapper.BamlMime.AreTypeAndSubTypeEqual(contentType))
                {
                    throw new Exception(SR.Format(SR.ContentTypeNotSupported, contentType));
                }
            }
 
            IStreamInfo bamlStream = stream as IStreamInfo;
 
            if (bamlStream == null || bamlStream.Assembly != component.GetType().Assembly)
            {
                throw new Exception(SR.Format(SR.UriNotMatchWithRootType, component.GetType( ), resourceLocator));
            }
 
            XamlReader.LoadBaml(stream, pc, component, bCloseStream);
        }
 
        /// <summary>
        /// Create logic tree from given resource Locator, and return the root of
        /// this tree.
        /// </summary>
        /// <param name="resourceLocator">Resource Locator</param>
        public static object LoadComponent(Uri resourceLocator)
        {
            ArgumentNullException.ThrowIfNull(resourceLocator);
 
            if (resourceLocator.OriginalString == null)
                throw new ArgumentException(SR.Format(SR.ArgumentPropertyMustNotBeNull,"resourceLocator", "OriginalString"));
 
            if (resourceLocator.IsAbsoluteUri == true)
                throw new ArgumentException(SR.AbsoluteUriNotAllowed);
 
            return LoadComponent(resourceLocator, false);
        }
 
        // <summary>
        // Create logic tree from given resource Locator, and return the root of
        // this tree.
        // </summary>
        // <param name="resourceLocator">Resource Locator</param>
        // <param name="bSkipJournaledProperties">SkipJournaledProperties or not</param>
        internal static object LoadComponent(Uri resourceLocator, bool bSkipJournaledProperties)
        {
            //
            // Only the Public LoadComponent(uri) and Journal navigation for PageFunction resume
            // call this method, the caller should have ensure the passed paramaters are valid.
            // So don't need to explicitly do the validation check for the parameters.
            //
 
            // Passed a relative Uri here.
            // needs to resolve it to Pack://Application.
            //..\..\ in the relative Uri will get stripped when creating the new Uri and resolving to the
            //PackAppBaseUri, i.e. only relative Uri within the appbase are created here
            Uri packUri = BindUriHelper.GetResolvedUri(BaseUriHelper.PackAppBaseUri, resourceLocator);
 
            PackagePart part = GetResourceOrContentPart(packUri);
            ContentType contentType = new ContentType(part.ContentType);
            Stream stream = part.GetSeekableStream();
 
            ParserContext pc = new ParserContext();
            pc.BaseUri = packUri;
            pc.SkipJournaledProperties = bSkipJournaledProperties;
 
            //
            // The stream must be a BAML or XAML stream.
            //
            if (MimeTypeMapper.BamlMime.AreTypeAndSubTypeEqual(contentType))
            {
                return LoadBamlStreamWithSyncInfo(stream, pc);
            }
            else if (MimeTypeMapper.XamlMime.AreTypeAndSubTypeEqual(contentType))
            {
                return XamlReader.Load(stream, pc);
            }
            else
            {
                throw new Exception(SR.Format(SR.ContentTypeNotSupported, contentType.ToString()));
            }
        }
 
 
        //
        // A helper method to create a tree from a baml stream.
        //
        // This helper will be called by BamlConverter and LoadComponent(Uri).
        //
        // If root element type in the bamlstream was compiled from a xaml file,
        // and the bamlstream created from the xaml file is exact same as the baml stream
        // passed in this method, we don't want to generate duplicate tree nodes.
        // Navigate(Uri) and LoadComponent(Uri) may hit this situation.
        //
        // The caller should prepare baml stream and appropriate ParserContext.
        //
        internal static object LoadBamlStreamWithSyncInfo(Stream stream, ParserContext pc)
        {
            object rootElement = null;
 
            // The callers should have already done the parameter validation.
            // So the code here uses assert instead of throwing exception.
            //
            Debug.Assert(stream != null, "stream should not be null.");
            Debug.Assert(pc != null, "pc should not be null.");
 
            if (s_NestedBamlLoadInfo == null)
            {
                s_NestedBamlLoadInfo = new Stack<NestedBamlLoadInfo>();
            }
 
            // Keep the Uri and Stream which is being handled by LoadBaml in this thread.
            // If the ctor of the root element in this tree calls the InitializeComponent
            // method, the baml loaded in that context will go through and this one will
            // be skipped to completion automatically, since the same stream will be used,
            // essentially making the LoadBaml in this helper a No-OP.
            //
            NestedBamlLoadInfo loadBamlSyncInfo = new NestedBamlLoadInfo(pc.BaseUri, stream, pc.SkipJournaledProperties);
 
            s_NestedBamlLoadInfo.Push(loadBamlSyncInfo);
            try
            {
                // LoadBaml will close the stream.
                rootElement = XamlReader.LoadBaml(stream, pc, null, true);
            }
            finally
            {
                // Reset the per-thread Uri & Stream setting to indicate that tree generation
                // from the baml stream is done.
                s_NestedBamlLoadInfo.Pop();
 
                if (s_NestedBamlLoadInfo.Count == 0)
                {
                    s_NestedBamlLoadInfo = null;
                }
            }
            return rootElement;
        }
 
        /// <summary>
        /// Get PackagePart for a uri, the uri maps to a resource which is embedded
        /// inside manifest resource "$(AssemblyName).g.resources" in Application or
        /// dependent library assembly.
        ///
        /// If the Uri doesn't map to any resource, this method returns null.
        ///
        /// The accepted uri could be relative uri or pack uri.
        ///
        ///   Such as
        ///    Resource from Application assembly
        ///         "image/picture1.jpg" or
        ///         "pack://application:,,,/image/picture1.jpg"
        ///
        ///    Resource from a library assembly
        ///         "mylibrary;component/image/picture2.png" or
        ///         "pack://application:,,,/mylibrary;component/image/picture3.jpg"
        ///
        /// </summary>
        /// <param name="uriResource">the uri maps to the resource</param>
        /// <returns>PackagePart or null</returns>
        public static StreamResourceInfo GetResourceStream(Uri uriResource)
        {
            ArgumentNullException.ThrowIfNull(uriResource);
 
            if (uriResource.OriginalString == null)
                throw new ArgumentException(SR.Format(SR.ArgumentPropertyMustNotBeNull, "uriResource", "OriginalString"));
 
            if (uriResource.IsAbsoluteUri == true && !BaseUriHelper.IsPackApplicationUri(uriResource))
            {
                throw new ArgumentException(SR.NonPackAppAbsoluteUriNotAllowed);
            }
 
            ResourcePart part = GetResourceOrContentPart(uriResource) as ResourcePart;
            return (part == null) ? null : new StreamResourceInfo(part.GetSeekableStream(), part.ContentType);
        }
 
        /// <summary>
        /// Get PackagePart for a uri, the uri maps to a content file which is associated
        /// with the application assembly.
        ///
        /// If the Uri doesn't map to any content file, this method returns null.
        ///
        /// The accepted uri could be relative uri or pack://Application:,,,/ uri.
        ///
        ///   Such as
        ///         "image/picture1.jpg"
        ///    or
        ///        "pack://application:,,,/image/picture1.jpg"
        ///
        /// </summary>
        /// <param name="uriContent">the uri maps to the Content File</param>
        /// <returns>PackagePart or null</returns>
        public static StreamResourceInfo GetContentStream(Uri uriContent)
        {
            ArgumentNullException.ThrowIfNull(uriContent);
 
            if (uriContent.OriginalString == null)
                throw new ArgumentException(SR.Format(SR.ArgumentPropertyMustNotBeNull, "uriContent", "OriginalString"));
 
            if (uriContent.IsAbsoluteUri == true && !BaseUriHelper.IsPackApplicationUri(uriContent))
            {
                throw new ArgumentException(SR.NonPackAppAbsoluteUriNotAllowed);
            }
 
            ContentFilePart part = GetResourceOrContentPart(uriContent) as ContentFilePart;
            return (part == null) ? null : new StreamResourceInfo(part.GetSeekableStream(), part.ContentType);
        }
 
        /// <summary>
        /// Get PackagePart for a uri, the uri maps to a file which comes from the place
        /// where the application was originally deployed.
        ///
        /// The accepted uri could be relative uri such as "foo.jpg"
        ///
        /// or  pack Uri, "pack://siteoforigin:,,,/foo.jpg"
        ///
        /// </summary>
        /// <param name="uriRemote">the uri maps to the resource</param>
        /// <returns>PackagePart or null</returns>
        public static StreamResourceInfo GetRemoteStream(Uri uriRemote)
        {
            SiteOfOriginPart sooPart = null;
 
            ArgumentNullException.ThrowIfNull(uriRemote);
 
            if (uriRemote.OriginalString == null)
                throw new ArgumentException(SR.Format(SR.ArgumentPropertyMustNotBeNull, "uriRemote", "OriginalString"));
 
            if (uriRemote.IsAbsoluteUri == true)
            {
                if (BaseUriHelper.SiteOfOriginBaseUri.IsBaseOf(uriRemote) != true)
                {
                    throw new ArgumentException(SR.NonPackSooAbsoluteUriNotAllowed);
                }
            }
 
            Uri resolvedUri = BindUriHelper.GetResolvedUri(BaseUriHelper.SiteOfOriginBaseUri, uriRemote);
 
            Uri packageUri = PackUriHelper.GetPackageUri(resolvedUri);
            Uri partUri = PackUriHelper.GetPartUri(resolvedUri);
 
            //
            // SiteOfOriginContainer must have been added into the package cache, the code should just
            // take use of that SiteOfOriginContainer instance, instead of creating a new instance here.
            //
            SiteOfOriginContainer sooContainer = (SiteOfOriginContainer)GetResourcePackage(packageUri);
 
            // the SiteOfOriginContainer is shared across threads;  synchronize access to it
            // using the same lock object as other uses (PackWebResponse+CachedResponse.GetResponseStream)
            lock (sooContainer)
            {
                sooPart = sooContainer.GetPart(partUri) as SiteOfOriginPart;
            }
 
            //
            // Verify if the sooPart is for a valid remote file.
            //
            Stream stream = null;
 
            if (sooPart != null)
            {
                try
                {
                    stream = sooPart.GetSeekableStream();
 
                    if (stream == null)
                    {
                        //
                        // Cannot get stream from this PackagePart for some unknown reason,
                        // since the code didn't throw WebException.
                        //
                        sooPart = null;
                    }
                }
                catch (WebException)
                {
                    // A WebException is thrown when the code tried to get stream from the PackagePart.
                    // The Uri passed to this method must be a wrong uri.
                    // Return null for this case.
                    sooPart = null;
 
                    // For all other exceptions such as security exception, etc, let it go to upper frame,
                    // and fail eventually if no exception handler wants to catch it.
                }
            }
 
            // When stream is not null, sooPart cannot be null either
            Debug.Assert( ((stream != null) && (sooPart == null)) != true,  "When stream is not null, sooPart cannot be null either");
 
            return (stream == null) ? null : new StreamResourceInfo(stream, sooPart.ContentType);
        }
 
        /// <summary>
        /// Gets the cookie for the uri. It will work only for site of origin.
        /// </summary>
        /// <param name="uri">The uri for which the cookie is to be read</param>
        /// <returns>The cookie, if it exsits, else an exception is thrown.</returns>
        /// <Remarks>
        ///     Callers must have FileIOPermission(FileIOPermissionAccess.Read) or WebPermission(NetworkAccess.Connect) for the Uri, depending on whether the Uri is a file Uri or not, to call this API.
        /// </Remarks>
        public static string GetCookie(Uri uri)
        {
            return CookieHandler.GetCookie(uri, true/*throwIfNoCookie*/);
        }
 
        /// <summary>
        /// Sets the cookie for the uri. It will work only for site of origin.
        /// </summary>
        /// <param name="uri">The uri for which the cookie is to be set</param>
        /// <param name="value">The value of the cookie. Should be name=value, but "value-only" cookies are also allowed. </param>
        /// <Remarks>
        ///     Callers must have FileIOPermission(FileIOPermissionAccess.Read) or WebPermission(NetworkAccess.Connect) for the Uri, depending on whether the Uri is a file Uri or not, to call this API.
        /// </Remarks>
        public static void SetCookie(Uri uri, string value)
        {
            CookieHandler.SetCookie(uri, value);
        }
 
        #endregion Public Methods
 
        //------------------------------------------------------
        //
        //  Public Properties
        //
        //------------------------------------------------------
 
        #region Public Properties
 
        /// <summary>
        ///     The Current property enables the developer to always get to the application in
        ///     AppDomain in which they are running.
        /// </summary>
        static public Application Current
        {
            get
            {
                // There is no need to take the _globalLock because reading a
                // reference is an atomic operation. Moreover taking a lock
                // also causes risk of re-entrancy because it pumps messages.
 
                return _appInstance;
            }
        }
 
        /// <summary>
        ///     The Windows property exposes a WindowCollection object, from which a developer
        ///     can iterate over all the windows that have been opened in the current application.
        /// </summary>
        // DO-NOT USE THIS PROPERY IF YOU MEAN TO MODIFY THE UNDERLYING COLLECTION.  USE
        // WindowsInternal PROPERTY FOR MODIFYING THE UNDERLYING DATASTRUCTURE.
        public WindowCollection Windows
        {
            get
            {
                VerifyAccess();
                return WindowsInternal.Clone();
            }
        }
 
        /// <summary>
        ///     The MainWindow property indicates the primary window of the application.
        ///     Note that setting the mainWindow property is not possible for browser hosted applications.
        /// </summary>
        /// <remarks>
        ///     By default - MainWindow will be set to the first window opened in the application.
        ///     However the MainWindow may be set programmatically to indicate "this is my main window".
        ///     It is a recommended programming style to refer to MainWindow in code instead of Windows[0].
        ///
        /// </remarks>
        public Window MainWindow
        {
            get
            {
                VerifyAccess();
                return _mainWindow;
            }
 
            set
            {
                VerifyAccess();
 
                if (value != _mainWindow)
                {
                    _mainWindow = value;
                }
            }
        }
 
        /// <summary>
        ///     The ShutdownMode property is called to set the shutdown specific mode of
        ///     the application. Setting this property controls the way in which an application
        ///     will shutdown.
        ///         The three values for the ShutdownMode enum are :
        ///                 OnLastWindowClose
        ///                 OnMainWindowClose
        ///                 OnExplicitShutdown
        ///
        ///         OnLastWindowClose - this mode will shutdown the application when  the
        ///                             last window is closed, or an explicit call is made
        ///                             to Application.Shutdown(). This is the default mode.
        ///
        ///         OnMainWindowClose - this mode will shutdown the application when the main
        ///                             window has been closed, or Application.Shutdown() is
        ///                             called. Note that if the MainWindow property has not
        ///                             been set - this mode is equivalent to OnExplicitOnly.
        ///
        ///         OnExplicitShutdown- this mode will shutdown the application only when an
        ///                             explicit call to OnShutdown() has been made.
        /// </summary>
        public ShutdownMode ShutdownMode
        {
            get
            {
                VerifyAccess();
                return _shutdownMode;
            }
 
            set
            {
                VerifyAccess();
                if ( !IsValidShutdownMode(value) )
                {
                    throw new InvalidEnumArgumentException("value", (int)value, typeof(ShutdownMode));
                }
                if (IsShuttingDown == true || _appIsShutdown == true)
                {
                    throw new InvalidOperationException(SR.ShutdownModeWhenAppShutdown);
                }
 
                _shutdownMode = value;
            }
        }
 
        /// <summary>
        ///     Current locally defined Resources
        /// </summary>
        [Ambient]
        public ResourceDictionary Resources
        {
            //Don't use  VerifyAccess() here since Resources can be set from any thread.
            //We synchronize access using _globalLock
 
            get
            {
                ResourceDictionary resources;
                bool needToAddOwner = false;
 
                lock(_globalLock)
                {
                    if (_resources == null)
                    {
                        // Shouldn't return null for property of type collection.
                        // It enables the Mort scenario: application.Resources.Add();
                        _resources = new ResourceDictionary();
                        needToAddOwner = true;
                    }
 
                    resources = _resources;
                }
 
                if (needToAddOwner)
                {
                    resources.AddOwner(this);
                }
 
                return resources;
            }
            set
            {
                bool invalidateResources = false;
                ResourceDictionary oldValue;
 
                lock(_globalLock)
                {
                    oldValue = _resources;
                    _resources = value;
                }
 
                if (oldValue != null)
                {
                    // This app is no longer an owner for the old RD
                    oldValue.RemoveOwner(this);
                }
 
                if(_reloadFluentDictionary && !_resourcesInitialized)
                {
                    if(value != null && ThemeMode != ThemeMode.None)
                    {
                        value.MergedDictionaries.Insert(0, ThemeManager.GetThemeDictionary(ThemeMode));
                    }
                    _reloadFluentDictionary = false;
                    invalidateResources = true;
                }
 
                if (value != null)
                {
                    if (!value.ContainsOwner(this))
                    {
                        // This app is an owner for the new RD
                        value.AddOwner(this);
                    }
                }
 
                if (oldValue != value)
                {
                    invalidateResources = true;
                }
 
                if (invalidateResources)
                {
                    InvalidateResourceReferences(new ResourcesChangeInfo(oldValue, value));
                }
            }
        }
 
        ResourceDictionary IHaveResources.Resources
        {
            get { return Resources; }
            set { Resources = value; }
        }
 
        /// <summary>
        /// Gets or sets the Fluent theme mode of the application.
        /// </summary>
        /// <remarks>
        /// Setting this property controls if Fluent theme is loaded in Light, Dark or System mode. 
        /// It also controls the application of backdrop and darkmode on window.
        /// The four values for the ThemeMode enum are :
        ///     <see cref="ThemeMode.None"/> - No Fluent theme is loaded.
        ///     <see cref="ThemeMode.System"/> - Fluent theme is loaded based on the system theme.
        ///     <see cref="ThemeMode.Light"/> - Fluent theme is loaded in Light mode.
        ///     <see cref="ThemeMode.Dark"/> - Fluent theme is loaded in Dark mode.
        ///
        /// These values are predefined in <see cref="ThemeMode"/> struct
        ///
        /// The default value is <see cref="ThemeMode.None"/>.
        ///     <see cref="ThemeMode"/> and <see cref="Resources"/> are designed to be in sync with each other.
        ///     Syncing is done in order to avoid UI inconsistencies, for example, if the application is in dark mode 
        ///     but the windows are in light mode or vice versa. 
        ///     
        ///     Setting this property loads the Fluent theme dictionaries in the application resources.
        ///     So, if you set this property, it is preferrable to not include Fluent theme dictionaries
        ///     in the application resources manually. If you do, the Fluent theme dictionaries added in the application
        ///     resources will take precedence over the ones added by setting this property.
        ///     
        ///     This property is experimental and may be removed in future versions.
        /// </remarks>
        [Experimental("WPF0001")]
        [TypeConverter(typeof(ThemeModeConverter))]
        public ThemeMode ThemeMode
        {
            get
            {
                return _themeMode;
            }
            set
            {
                VerifyAccess();
                if (!ThemeManager.IsValidThemeMode(value))
                {
                    throw new ArgumentException(string.Format("ThemeMode value {0} is invalid. Use None, System, Light or Dark", value));
                }
                
                ThemeMode oldValue = _themeMode;
                _themeMode = value;
 
                if(!_resourcesInitialized)
                {
 
                    ThemeManager.OnApplicationThemeChanged(oldValue, value);
 
                    // If the resources are not initializd, fluent dictionary
                    // included in this operation will be reset.
                    // Hence, we need to reload the fluent dictionary.
                    _reloadFluentDictionary = true;
 
                    // OnApplicationThemeChanged will trigger InvalidateResourceReferences
                    // which will mark _resourcesInitialized = true, however since 
                    // the value earlier was false, it means that Resources may not have been
                    // parsed from BAML yet. Hence, we need to reset the value to false.
                    _resourcesInitialized = false;
 
                    return;
                }
 
                ThemeManager.OnApplicationThemeChanged(oldValue, value);
            }
        }
 
        bool IQueryAmbient.IsAmbientPropertyAvailable(string propertyName)
        {
            // We want to make sure that StaticResource resolution checks the .Resources
            // Ie.  The Ambient search should look at Resources if it is set.
            // Even if it wasn't set from XAML (eg. the Ctor (or derived Ctor) added stuff)
            return (propertyName == "Resources" && _resources != null);
        }
 
        // Says if App.Resources has any implicit styles
        internal bool HasImplicitStylesInResources
        {
            get { return _hasImplicitStylesInResources; }
            set { _hasImplicitStylesInResources = value; }
        }
 
        /// <summary>
        /// The main page
        /// </summary>
        /// <remarks>
        /// This property should only be called from the Application thread
        /// </remarks>
        public Uri StartupUri
        {
            get
            {
                // Don't call VerifyAccess.  System.Printing can call this from another thread.
                return _startupUri;
            }
            set
            {
                VerifyAccess();
                ArgumentNullException.ThrowIfNull(value);
 
                _startupUri = value;
            }
        }
 
 
        /// <summary>
        /// Gets the property Hashtable.
        /// </summary>
        /// <returns>IDictionary interface</returns>
        /// <remarks>
        /// This property is accessible from any thread
        /// </remarks>
        public IDictionary Properties
        {
            get
            {
                // change from before; Before we used to return null
                // but that might throw a nullpointer exception if
                // indexers are being used on the Hashtable object
                lock(_globalLock)
                {
                    if (_htProps == null)
                    {
                        // so we will have 5 entries before we resize
                        _htProps = new HybridDictionary(5);
                    }
                    return _htProps;
                }
            }
        }
 
 
        /// <summary>
        /// This property gets and sets the assembly pack://application:,,,/ refers to.
        /// </summary>
        public static Assembly ResourceAssembly
        {
            get
            {
                if (_resourceAssembly == null)
                {
                    lock (_globalLock)
                    {
                        _resourceAssembly = Assembly.GetEntryAssembly();
                    }
                }
 
                return _resourceAssembly;
            }
            set
            {
                lock (_globalLock)
                {
                    if (_resourceAssembly != value)
                    {
                        if ((_resourceAssembly == null) && (Assembly.GetEntryAssembly() == null))
                        {
                            _resourceAssembly = value;
                            BaseUriHelper.ResourceAssembly = value;
                        }
                        else
                        {
                            throw new InvalidOperationException(SR.Format(SR.PropertyIsImmutable, "ResourceAssembly", "Application"));
                        }
                    }
                }
            }
        }
 
        #endregion Public Properties
 
        //------------------------------------------------------
        //
        //  Public Events
        //
        //------------------------------------------------------
 
        #region Public Events
        /// <summary>
        ///     The Startup event is fired when an application is starting.
        ///     This event is raised by the OnStartup method.
        /// </summary>
        public event StartupEventHandler Startup
        {
            add{ VerifyAccess(); Events.AddHandler(EVENT_STARTUP, value); }
            remove{ VerifyAccess(); Events.RemoveHandler(EVENT_STARTUP, value); }
        }
 
        /// <summary>
        /// The Exit event is fired when an application is shutting down.
        /// This event is raised by the OnExit method.
        /// </summary>
        public event ExitEventHandler Exit
        {
            add{ VerifyAccess(); Events.AddHandler(EVENT_EXIT, value); }
            remove{ VerifyAccess(); Events.RemoveHandler(EVENT_EXIT, value); }
        }
 
        /// <summary>
        /// The Activated event is fired when an applications window has been activated from
        /// the OS ( alt-tab, or changing application from taskbar, or clicking on a winodw).
        /// This event is raised by the OnActivated method.
        /// </summary>
        public event EventHandler Activated;
 
        /// <summary>
        /// The Deactivated event is fired when an applications window has been de-activated
        /// from the OS ( alt-tab, or changing application from taskbar, or clicking away
        /// from an applications window). This event is raised by the OnDeactivated method.
        /// </summary>
        public event EventHandler Deactivated;
 
        /// <summary>
        /// The SessionEnding event is fired when windows is ending, either due to a shutdown,
        /// or loggoff from the start menu ( or calling the ExitWindows function).  The
        /// ReasonSessionEnding enum on the  SessionEndingEventArgs indicates whether the session
        /// is ending in response to a shutdown of the OS, or if the user is logging off.
        /// </summary>
        public event SessionEndingCancelEventHandler SessionEnding
        {
            add{ VerifyAccess(); Events.AddHandler(EVENT_SESSIONENDING, value); }
            remove{ VerifyAccess(); Events.RemoveHandler(EVENT_SESSIONENDING, value); }
        }
 
        /// <summary>
        /// The DispatcherUnhandledException event is fired when an unhandled exception
        /// is caught at the Dispatcher level (by the dispatcher).
        /// </summary>
        public event DispatcherUnhandledExceptionEventHandler DispatcherUnhandledException
        {
            //Dispatcher.Invoke will call the callback on the dispatcher thread so a VerifyAccess()
            //check is redundant (and wrong) outside the invoke call
 
            add
            {
                Dispatcher.Invoke(
                    DispatcherPriority.Send,
                    (DispatcherOperationCallback) delegate(object unused)
                    {
                        Dispatcher.UnhandledException += value;
                        return null;
                    },
                    null);
            }
            remove
            {
                Dispatcher.Invoke(
                    DispatcherPriority.Send,
                    (DispatcherOperationCallback) delegate(object unused)
                    {
                        Dispatcher.UnhandledException -= value;
                        return null;
                    },
                    null);
            }
        }
 
        /// <summary>
        /// </summary>
        public event NavigatingCancelEventHandler Navigating;
 
        /// <summary>
        /// </summary>
        public event NavigatedEventHandler Navigated;
 
        /// <summary>
        /// </summary>
        public event NavigationProgressEventHandler NavigationProgress;
 
        /// <summary>
        /// This event is fired when an error is encountered during a navigation
        /// </summary>
        public event NavigationFailedEventHandler NavigationFailed;
 
        /// <summary>
        /// </summary>
        public event LoadCompletedEventHandler LoadCompleted;
 
        /// <summary>
        /// </summary>
        public event NavigationStoppedEventHandler NavigationStopped;
 
        /// <summary>
        /// </summary>
        public event FragmentNavigationEventHandler FragmentNavigation;
        #endregion Public Events
 
        //------------------------------------------------------
        //
        //  Protected Methods
        //
        //------------------------------------------------------
 
        #region Protected Methods
        /// <summary>
        ///     OnStartup is called to raise the Startup event. The developer will typically override this method
        ///     if they want to take action at startup time ( or they may choose to attach an event).
        ///     This method will be called once when the application begins, once that application's Run() method
        ///     has been called.
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual method
        ///     that raises an event, to provide a convenience for developers that subclass the event.
        ///     If you override this method - you need to call Base.OnStartup(...) for the corresponding event
        ///     to be raised.
        /// </remarks>
        /// <param name="e">The event args that will be passed to the Startup event</param>
        protected virtual void OnStartup(StartupEventArgs e)
        {
            VerifyAccess();
 
            StartupEventHandler handler = (StartupEventHandler)Events[EVENT_STARTUP];
            if (handler != null)
            {
                handler(this, e);
            }
        }
 
        /// <summary>
        ///     OnExit is called to raise the Exit event.
        ///     The developer will typically override this method if they want to take
        ///     action when the application exits  ( or they may choose to attach an event).
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual method
        ///     that raises an event, to provide a convenience for developers that subclass the event.
        ///     If you override this method - you need to call Base.OnExit(...) for the
        ///     corresponding event to be raised.
        /// </remarks>
        /// <param name="e">The event args that will be passed to the Exit event</param>
        protected virtual void OnExit(ExitEventArgs e)
        {
            VerifyAccess();
 
            ExitEventHandler handler = (ExitEventHandler)Events[EVENT_EXIT];
            if (handler != null)
            {
                handler(this, e);
            }
        }
 
        /// <summary>
        ///     OnActivated is called to raise the Activated event.
        ///     The developer will typically override this method if they want to take action
        ///     when the application gets activated ( or they may choose to attach an event).
        ///     This method will be called when one of the current applications windows gets
        ///     activated on the desktop. ( This corresponds to Users WM_ACTIVATEAPP message).
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected
        ///     virtual method that raises an event, to provide a convenience for developers
        ///     that subclass the event.
        /// </remarks>
        /// <param name="e"></param>
        protected virtual void OnActivated(EventArgs e)
        {
            VerifyAccess();
            if (Activated != null)
            {
                Activated(this, e);
            }
        }
 
        /// <summary>
        ///     OnDeactivated is called to raise the Deactivated event. The developer will
        ///     typically override this method if they want to take action when the application
        ///     gets deactivated ( or they may choose to attach an event).
        ///     This method will be called when one of the current applications windows gets
        ///     activated on the desktop. ( This corresponds to Users WM_ACTIVATEAPP message,
        ///     with an wparam indicating the app is being deactivated).
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that
        ///     subclass the event.
        /// </remarks>
        /// <param name="e"></param>
        protected virtual void OnDeactivated(EventArgs e)
        {
            VerifyAccess();
            if (Deactivated != null)
            {
                Deactivated(this, e);
            }
        }
 
        /// <summary>
        ///     OnSessionEnding is called to raise the SessionEnding event. The developer will
        ///     typically override this method if they want to take action when the OS is ending
        ///     a session ( or they may choose to attach an event). This method will be called when
        ///     the user has chosen to either logoff or shutdown. These events are equivalent
        ///     to receiving a WM_QUERYSESSION window event. Windows will send it when user is
        ///     logging out/shutting down. ( See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/wm_queryendsession.asp ).
        ///     By default if this event is not cancelled - Avalon will then call Application.Shutdown.
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that subclass
        ///     the event.
        /// </remarks>
        /// <param name="e"></param>
        protected virtual void OnSessionEnding(SessionEndingCancelEventArgs e)
        {
            VerifyAccess();
 
            SessionEndingCancelEventHandler handler = (SessionEndingCancelEventHandler)Events[EVENT_SESSIONENDING];
            if (handler != null)
            {
                handler(this, e);
            }
        }
 
        /// <summary>
        /// This method fires the Navigating event
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that subclass
        ///     the event. If you override this method - you need to call Base.OnNavigating(...) for
        ///     the corresponding event to be raised.
        /// </remarks>
        /// <param name="e">NavigationEventArgs</param>
        protected virtual void OnNavigating(NavigatingCancelEventArgs e)
        {
            VerifyAccess();
            if (Navigating != null)
            {
                Navigating(this, e);
            }
        }
 
        /// <summary>
        /// This method fires the Navigated event
        /// on receiving all of the stream contents
        /// for the given bpu
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that subclass
        ///     the event. If you override this method - you need to call Base.OnNavigated(...) for
        ///     the corresponding event to be raised.
        /// </remarks>
        /// <param name="e">NavigationEventArgs</param>
        protected virtual void OnNavigated(NavigationEventArgs e)
        {
            VerifyAccess();
            if (Navigated != null)
            {
                Navigated(this, e);
            }
        }
 
        /// <summary>
        /// This method fires the NavigationProgress event
        /// each time number of bytes equal to bytesInterval is read
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that subclass
        ///     the event. If you override this method - you need to call Base.OnNavigationProgress(...) for
        ///     the corresponding event to be raised.
        /// </remarks>
        /// <param name="e">NavigationEventArgs</param>
        protected virtual void OnNavigationProgress(NavigationProgressEventArgs e)
        {
            VerifyAccess();
            if (NavigationProgress != null)
            {
                NavigationProgress(this, e);
            }
        }
 
        /// <summary>
        /// This method fires the NavigationFailed event
        /// When there is an error encountered in navigation
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that subclass
        ///     the event. If you override this method - you need to call Base.OnNavigationProgress(...) for
        ///     the corresponding event to be raised.
        /// </remarks>
        /// <param name="e">NavigationFailedEventArgs</param>
        protected virtual void OnNavigationFailed(NavigationFailedEventArgs e)
        {
            VerifyAccess();
            if (NavigationFailed != null)
            {
                NavigationFailed(this, e);
            }
        }
 
        /// <summary>
        /// This method fires the LoadCompleted event
        /// after parsing all of the top level page
        /// and its secondary contents
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that subclass
        ///     the event. If you override this method - you need to call Base.OnLoadCompleted(...) for
        ///     the corresponding event to be raised.
        /// </remarks>
        /// <param name="e">NavigationEventArgs</param>
        protected virtual void OnLoadCompleted(NavigationEventArgs e)
        {
            VerifyAccess();
            if (LoadCompleted != null)
            {
                LoadCompleted(this, e);
            }
        }
 
        /// <summary>
        /// This method fires the Stopped event
        /// whenever the top level has navigated and
        /// there occurs a stop after that
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that subclass
        ///     the event. If you override this method - you need to call Base.OnNavigationStopped(...) for
        ///     the corresponding event to be raised.
        /// </remarks>
        /// <param name="e">NavigationEventArgs</param>
        protected virtual void OnNavigationStopped(NavigationEventArgs e)
        {
            VerifyAccess();
            if (NavigationStopped != null)
            {
                NavigationStopped(this, e);
            }
        }
 
 
        /// <summary>
        /// This method fires the FragmentNavigation event
        /// whenever a navigation to a uri containing a fragment
        /// occurs.
        /// </summary>
        /// <remarks>
        ///     This method follows the .Net programming guideline of having a protected virtual
        ///     method that raises an event, to provide a convenience for developers that subclass
        ///     the event. If you override this method - you need to call Base.OnNavigationStopped(...) for
        ///     the corresponding event to be raised.
        /// </remarks>
        /// <param name="e">FragmentNavigationEventArgs</param>
        protected virtual void OnFragmentNavigation(FragmentNavigationEventArgs e)
        {
            VerifyAccess();
            if (FragmentNavigation != null)
            {
                FragmentNavigation(this, e);
            }
        }
        #endregion Protected Methods
 
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------
 
        #region Internal Methods
 
        // It would be nice to make this FamANDAssem (protected and internal) if c# supported it
        internal virtual void PerformNavigationStateChangeTasks(
            bool isNavigationInitiator, bool playNavigatingSound, NavigationStateChange state)
        {
            if (isNavigationInitiator)
            {
                switch (state)
                {
                    case NavigationStateChange.Navigating:
                        if (playNavigatingSound)
                        {
                            PlaySound(SOUND_NAVIGATING);
                        }
                        break;
                    case NavigationStateChange.Completed:
                        PlaySound(SOUND_COMPLETE_NAVIGATION);
                        break;
                    case NavigationStateChange.Stopped:
                        break;
                }
            }
        }
 
 
        /// <summary>
        /// Application Startup.
        /// </summary>
        internal void DoStartup()
        {
            Debug.Assert(CheckAccess(), "This should only be called on the Application thread");
 
            if (StartupUri != null)
            {
                if (StartupUri.IsAbsoluteUri == false)
                {
                    // Resolve it against the ApplicationMarkupBaseUri.
                    StartupUri = new Uri(ApplicationMarkupBaseUri, StartupUri);
                }
 
                // ArrowHead Optimization for StartupUri:
                // When loading app resources (pack://application, we do not need to go through the navigation logic.
                // We can load the stream through ResourceContainer directly. This way we avoid loading the navigation
                // and webrequest code. It is also sync, instead of async if going through navigation code pass.
                // This optimization saves about 3-4% cold startup time for a simple application.
                // However, we need to maintain back compact in the following areas until we can do breaking change.
                // 1. Continue to support other uri and content types (the else statement).
                // 2. Continue to fire Navigating events.
                if (BaseUriHelper.IsPackApplicationUri(StartupUri))
                {
                    // BACK COMPAT:
                    // We need to fire Navigating event to be back compact with V1.
                    // We should drop this when we can do breaking change.
                    Uri relativeUri = BindUriHelper.GetUriRelativeToPackAppBase(StartupUri);
                    NavigatingCancelEventArgs e = new NavigatingCancelEventArgs(relativeUri, null, null, null, NavigationMode.New, null, null, true);
                    FireNavigating(e, true);
 
                    // Navigating can be cancelled.
                    if (! e.Cancel)
                    {
                        object root = LoadComponent(StartupUri, false);
 
                        // If the root element is not a window, we need to create a window.
                        ConfigAppWindowAndRootElement(root, StartupUri);
                    }
                }
                else
                {
                    // BACK COMPAT:
                    // The following logic is for pack://siteoforign uri syntax and all other uri and content types
                    // that the WPF navigation framework supports, including Html.
                    //
                    // We want to maintain the V1 behavior to continue support loading those content. I suggest reconsidering
                    // this support when we can do breaking change. We need to understand what scenarios require
                    // the Application StartupUri to load content other than xaml/baml in the app resource or content file.
                    // If there are no interesting ones, we should remove this support.
                    NavService = new NavigationService(null);
                    NavService.AllowWindowNavigation = true;
                    NavService.PreBPReady += new BPReadyEventHandler(OnPreBPReady);
                    NavService.Navigate(StartupUri);
                }
            }
        }
 
        /// <summary>
        /// DO NOT USE - internal method
        /// </summary>
        internal virtual void DoShutdown()
        {
            Debug.Assert(CheckAccess() == true, "DoShutdown can only be called on the Dispatcer thread");
            // We need to know if we have been shut down already.
            // We cannot check the IsShuttingDown variable because it is set true
            // in the function that calls us.
 
            // We use a while loop like this because closing a window will modify the windows list.
            while(WindowsInternal.Count > 0)
            {
                if (!WindowsInternal[0].IsDisposed)
                {
                    WindowsInternal[0].InternalClose(true, true);
                }
                else
                {
                    WindowsInternal.RemoveAt(0);
                }
            }
            WindowsInternal = null;
 
            ExitEventArgs e = new ExitEventArgs(_exitCode);
 
            // Event handler exception continuality: if exception occurs in ShuttingDown event handler,
            // our cleanup action is to finish Shuttingdown.  Since Shuttingdown cannot be cancelled.
            // We don't want user to use throw exception and catch it to cancel Shuttingdown.
            try
            {
                // fire Applicaiton Exit event
                OnExit(e);
            }
            finally
            {
                SetExitCode(e._exitCode);
 
                // By default statics are shared across appdomains, so need to clear
                lock (_globalLock)
                {
                    _appInstance = null;
                }
 
                _mainWindow = null;
                _htProps = null;
                NonAppWindowsInternal = null;
 
                // this will always be null in the browser hosted case since we we don't
                // support Activate, Deactivate, and SessionEnding events in the
                // browser scenario and thus we never create this hwndsource.
                if (_parkingHwnd != null)
                {
                    _parkingHwnd.Dispose();
                }
 
                if (_events != null)
                {
                    _events.Dispose();
                }
 
                PreloadedPackages.Clear();
                AppSecurityManager.ClearSecurityManager();
 
                _appIsShutdown = true; // mark app as shutdown
            }
        }
 
        //
        // This function is called from the public Run methods to start the application.
        // ApplicationProxyInternal.Run method calls this method directly to bypass the check
        // for browser hosted application in the public Run() method
        //
        internal int RunInternal(Window window)
        {
            VerifyAccess();
 
#if DEBUG_CLR_MEM
            if (CLRProfilerControl.ProcessIsUnderCLRProfiler &&
               (CLRProfilerControl.CLRLoggingLevel >= CLRProfilerControl.CLRLogState.Performance))
            {
                CLRProfilerControl.CLRLogWriteLine("Application_Run");
            }
#endif // DEBUG_CLR_MEM
 
            EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordGeneral | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientAppRun);
 
            //
            // (Can't create app and do run/shutdown followed
            // by run/shutdown)
            //
            // Devs could write the following code
            //
            // Application app = new Application();
            // app.Run();
            // app.Run();
            //
            // In this case, we should throw an exception when Run is called for the second time.
            // When app is shutdown, _appIsShutdown is set to true.  If it is true here, then we
            // throw an exception
            if (_appIsShutdown == true)
            {
                throw new InvalidOperationException(SR.Format(SR.CannotCallRunMultipleTimes, this.GetType().FullName));
            }
 
            if (window != null)
            {
                if (window.CheckAccess() == false)
                {
                    throw new ArgumentException(SR.Format(SR.WindowPassedShouldBeOnApplicationThread, window.GetType().FullName, this.GetType().FullName));
                }
 
                if (WindowsInternal.HasItem(window) == false)
                {
                    WindowsInternal.Add(window);
                }
 
                if (MainWindow == null)
                {
                    MainWindow = window;
                }
 
                if (window.Visibility != Visibility.Visible)
                {
                    Dispatcher.BeginInvoke(
                        DispatcherPriority.Send,
                        (DispatcherOperationCallback) delegate(object obj)
                        {
                            Window win = obj as Window;
                            win.Show();
                            return null;
                        },
                        window);
                }
            }
 
            EnsureHwndSource();
 
            //Even if the subclass app cancels the event we still want to create and run the dispatcher
            //so that when the app explicitly calls Shutdown, we have a dispatcher to service the posted
            //Shutdown DispatcherOperationCallback
 
            // Invoke the Dispatcher synchronously if we are not in the browser
            RunDispatcher(null);
 
            return _exitCode;
        }
 
        internal void InvalidateResourceReferences(ResourcesChangeInfo info)
        {
            _resourcesInitialized = true;
            
            // Sync needs to be performed only under the following conditions:
            //  - the resource change event raised is due to a collection change
            //      i.e. it is not a IsIndividualResourceAddOperation
            //  - the event is not raised due to the change in Application.ThemeMode
            //      i.e. SkipAppThemeModeSyncing is set to true
            if (!info.IsIndividualResourceChange
                    && !ThemeManager.SkipAppThemeModeSyncing)
            {
                ThemeManager.SyncApplicationThemeMode();
            }
            
            // Invalidate ResourceReference properties on all the windows.
            // we Clone() the collection b/c if we don't then some other thread can be
            // modifying the collection while we iterate over it
            InvalidateResourceReferenceOnWindowCollection(WindowsInternal.Clone(), info);
            InvalidateResourceReferenceOnWindowCollection(NonAppWindowsInternal.Clone(), info);
        }
 
        // Creates and returns a NavigationWindow for standalone cases
        // For browser hosted cases, returns the existing RootBrowserWindow which
        //   is created before the application.Run is called.
        internal NavigationWindow GetAppWindow()
        {
            NavigationWindow appWin = new NavigationWindow();
 
            // We don't want to show the window before the content is ready, but for compatibility reasons
            // we do want it to have an HWND available.  Not doing this can cause Application's MainWindow
            // to be null when LoadCompleted has happened.
            new WindowInteropHelper(appWin).EnsureHandle();
 
            return appWin;
        }
 
 
        internal void FireNavigating(NavigatingCancelEventArgs e, bool isInitialNavigation)
        {
            PerformNavigationStateChangeTasks(e.IsNavigationInitiator, !isInitialNavigation, NavigationStateChange.Navigating);
 
            OnNavigating(e);
        }
 
        internal void FireNavigated(NavigationEventArgs e)
        {
            OnNavigated(e);
        }
 
        internal void FireNavigationProgress(NavigationProgressEventArgs e)
        {
            OnNavigationProgress(e);
        }
 
        internal void FireNavigationFailed(NavigationFailedEventArgs e)
        {
            // Browser downloading state not reset; case 1.
            PerformNavigationStateChangeTasks(true, false, NavigationStateChange.Stopped);
 
            OnNavigationFailed(e);
        }
 
        internal void FireLoadCompleted(NavigationEventArgs e)
        {
            PerformNavigationStateChangeTasks(e.IsNavigationInitiator, false, NavigationStateChange.Completed);
 
            OnLoadCompleted(e);
        }
 
        internal void FireNavigationStopped(NavigationEventArgs e)
        {
            PerformNavigationStateChangeTasks(e.IsNavigationInitiator, false, NavigationStateChange.Stopped);
 
            OnNavigationStopped(e);
        }
 
        internal void FireFragmentNavigation(FragmentNavigationEventArgs e)
        {
            OnFragmentNavigation(e);
        }
 
        #endregion Internal methods
 
        //------------------------------------------------------
        //
        //  Internal Properties
        //
        //------------------------------------------------------
 
        #region Internal Properties
 
        // The public Windows property returns a copy of the underlying
        // WindowCollection.  This property is used internally to enable
        // modyfying the underlying collection.
        internal WindowCollection WindowsInternal
        {
            get
            {
                lock(_globalLock)
                {
                    if(_appWindowList == null)
                    {
                        _appWindowList = new WindowCollection();
                    }
                    return _appWindowList;
                }
            }
            private set
            {
                lock(_globalLock)
                {
                    _appWindowList = value;
                }
            }
        }
 
        internal WindowCollection NonAppWindowsInternal
        {
            get
            {
                lock(_globalLock)
                {
                    if (_nonAppWindowList == null)
                    {
                        _nonAppWindowList = new WindowCollection();
                    }
                    return _nonAppWindowList;
                }
            }
 
            private set
            {
                lock(_globalLock)
                {
                    _nonAppWindowList = value;
                }
            }
        }
 
        //This property indicates what type of an application was created. We use this
        //to determine whether to update the address bar or not for toplevel navigations
        //Since we don't currently have support to represent a proper relative uri
        //for .xps or .deploy or browser hosted exes, we limit address bar
        //updates to xaml navigations.
        //In the future, IBrowserCallbackServices and this should be moved to use RootBrowserWindow
        //instead of being in the application. For example,if a standalone window is created
        //in the same application, we still try to use IBrowserCallbackServices in the
        //standalone window. Need to ensure only RootBrowserWindow knows about browser hosting,
        //rest of the appmodel code should be agnostic to hosting process.
        //This will be cleaned up with the RootBrowserWindow cleanup.
        internal MimeType MimeType
        {
            get { return _appMimeType; }
            set { _appMimeType = value; }
        }
 
        // this is called from ApplicationProxyInternal, ProgressBarAppHelper, and ContainerActivationHelper.
        // All of these are on the app thread
        internal IServiceProvider ServiceProvider
        {
            private get
            {
                VerifyAccess();
                if (_serviceProvider != null)
                {
                    return _serviceProvider;
                }
                else
                {
                    return null;
                }
            }
            set
            {
                VerifyAccess();
                _serviceProvider = value ;
            }
        }
 
 
        // is called by NavigationService to detect TopLevel container
        // We check there to call this only if NavigationService is on
        // the same thread as the Application
        internal NavigationService NavService
        {
            get
            {
                VerifyAccess();
                return _navService;
            }
            set
            {
                VerifyAccess();
                _navService = value;
            }
        }
 
        internal static bool IsShuttingDown
        {
            get
            {
                //If we are shutting down normally, Application.IsShuttingDown will be true. Be sure to check this first.
                // If we are browser hosted, BrowserCallbackServices.IsShuttingDown checks to see if the browser is shutting us down,
                // even if we may not be shutting down the Application yet. Check this to avoid reentrance issues between the time that
                // browser is shutting us down and that Application.Shutdown (CriticalShutdown) is invoked.
                if (_isShuttingDown)
                {
                    return _isShuttingDown;
                }
 
                return false;
            }
            set
            {
                lock(_globalLock)
                {
                    _isShuttingDown = value;
                }
            }
        }
 
        // This returns the static variable _isShuttingDown.
        internal static bool IsApplicationObjectShuttingDown
        {
            get
            {
                return _isShuttingDown;
            }
        }
 
        /// <summary>
        /// Returns the handle of the parking window.
        /// </summary>
        internal IntPtr ParkingHwnd
        {
            get
            {
                if (_parkingHwnd != null)
                {
                    return _parkingHwnd.Handle;
                }
                else
                {
                    return IntPtr.Zero;
                }
            }
        }
 
        //
        // Keep the BaseUri for the application definition xaml markup stream.
        //
        // If the appdef xaml file is not in the project root directory, the baseUri for this
        // xaml file is not same as PackAppBaseUri.
        //
        // If StartupUri is set to a relative Uri, it should be resolved against this
        // ApplicationMarkupBaseUri before the uri is passed to NavigationService methods.
        //
        internal Uri ApplicationMarkupBaseUri
        {
            get
            {
                if (_applicationMarkupBaseUri == null)
                {
                    _applicationMarkupBaseUri = BaseUriHelper.BaseUri;
                }
 
                return _applicationMarkupBaseUri;
            }
 
            set
            {
                _applicationMarkupBaseUri = value;
            }
        }
 
        #endregion Internal Properties
 
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------
        #region Private Methods
        // <summary>
        // Sets up several things on startup.  If you want to use avalon services without using the
        // Application class you will need to call this method explicitly.  Standard avalon applications
        // will not have to worry about this detail.
        // </summary>
        private static void ApplicationInit()
        {
            _globalLock = new object();
 
            // Add an instance of the ResourceContainer to PreloadedPackages so that PackWebRequestFactory can find it
            // and mark it as thread-safe so PackWebResponse won't protect returned streams with a synchronizing wrapper
            PreloadedPackages.AddPackage(PackUriHelper.GetPackageUri(BaseUriHelper.PackAppBaseUri), new ResourceContainer(), true);
 
 
            MimeObjectFactory.RegisterCore(MimeTypeMapper.BamlMime, new StreamToObjectFactoryDelegateCore(AppModelKnownContentFactory.BamlConverterCore));
 
            StreamToObjectFactoryDelegateCore xamlFactoryDelegate = new StreamToObjectFactoryDelegateCore(AppModelKnownContentFactory.XamlConverterCore);
 
            MimeObjectFactory.RegisterCore(MimeTypeMapper.XamlMime, xamlFactoryDelegate);
            MimeObjectFactory.RegisterCore(MimeTypeMapper.FixedDocumentMime, xamlFactoryDelegate);
            MimeObjectFactory.RegisterCore(MimeTypeMapper.FixedDocumentSequenceMime, xamlFactoryDelegate);
            MimeObjectFactory.RegisterCore(MimeTypeMapper.FixedPageMime, xamlFactoryDelegate);
            MimeObjectFactory.RegisterCore(MimeTypeMapper.ResourceDictionaryMime, xamlFactoryDelegate);
 
            StreamToObjectFactoryDelegateCore htmlxappFactoryDelegate = new StreamToObjectFactoryDelegateCore(AppModelKnownContentFactory.HtmlXappConverterCore);
            MimeObjectFactory.RegisterCore(MimeTypeMapper.HtmMime, htmlxappFactoryDelegate);
            MimeObjectFactory.RegisterCore(MimeTypeMapper.HtmlMime, htmlxappFactoryDelegate);
            MimeObjectFactory.RegisterCore(MimeTypeMapper.XbapMime, htmlxappFactoryDelegate);
 
        }
 
        // This function returns the resource stream including resource and content file.
        // This is called by GetContentStream and GetResourceStream.
        // NOTE: when we can do breaking change, we should consider uniting GetContentStream
        // with GetResourceStream. Developer should not need to know and be able to get the
        // stream based on the uri (pack application).
        private static PackagePart GetResourceOrContentPart(Uri uri)
        {
            // Caller examines the input parameter.
            // It should be either a relative or pack application uri here.
            Debug.Assert(!uri.IsAbsoluteUri || BaseUriHelper.IsPackApplicationUri(uri));
            Uri packAppUri = BaseUriHelper.PackAppBaseUri;
            Uri resolvedUri = BindUriHelper.GetResolvedUri(packAppUri, uri);
 
            Uri packageUri = PackUriHelper.GetPackageUri(resolvedUri);
            Uri partUri = PackUriHelper.GetPartUri(resolvedUri);
 
            //
            // ResourceContainer must have been added into the package cache, the code should just
            // take use of that ResourceContainer instance, instead of creating a new instance here.
            //
            ResourceContainer resContainer = (ResourceContainer)GetResourcePackage(packageUri);
 
            // the ResourceContainer is shared across threads;  synchronize access to it
            // using the same lock object as other uses (PackWebResponse+CachedResponse.GetResponseStream)
            PackagePart part = null;
            lock (resContainer)
            {
                part = resContainer.GetPart(partUri);
            }
 
            return part;
        }
 
        /// <summary> Helper for getting the pack://application or pack://siteoforigin resource package. </summary>
        /// <param name="packageUri"> "application://" or "siteoforigin://" </param>
        private static Package GetResourcePackage(Uri packageUri)
        {
            Package package = PreloadedPackages.GetPackage(packageUri);
            if (package == null)
            {
                Uri packUri = PackUriHelper.Create(packageUri);
                Invariant.Assert(packUri == BaseUriHelper.PackAppBaseUri || packUri == BaseUriHelper.SiteOfOriginBaseUri,
                    $"Unknown packageUri passed: {packageUri}");
 
                Invariant.Assert(IsApplicationObjectShuttingDown);
                throw new InvalidOperationException(SR.ApplicationShuttingDown);
            }
            return package;
        }
 
        /// <summary>
        ///     Creates hwndsource so that we can listen to some window msgs.
        /// </summary>
        private void EnsureHwndSource()
        {
            if (_parkingHwnd == null)
            {
                // _appFilterHook needs to be member variable otherwise
                // it is GC'ed and we don't get messages from HwndWrapper
                // (HwndWrapper keeps a WeakReference to the hook)
 
                _appFilterHook = new HwndWrapperHook(AppFilterMessage);
                HwndWrapperHook[] wrapperHooks = {_appFilterHook};
 
                _parkingHwnd = new HwndWrapper(
                                0,
                                0,
                                0,
                                0,
                                0,
                                0,
                                0,
                                "",
                                IntPtr.Zero,
                                wrapperHooks);
            }
        }
 
        private IntPtr AppFilterMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            IntPtr retInt = IntPtr.Zero;
            switch ((WindowMessage)msg)
            {
                case WindowMessage.WM_ACTIVATEAPP:
                    handled = WmActivateApp(NativeMethods.IntPtrToInt32(wParam));
                    break;
                case WindowMessage.WM_QUERYENDSESSION :
                    handled = WmQueryEndSession(lParam, ref retInt);
                    break;
                default:
                    handled = false;
                    break;
            }
            return retInt;
        }
 
        private bool WmActivateApp(Int32 wParam)
        {
            int temp = wParam;
            bool isActivated = (temp == 0? false : true);
 
            // Event handler exception continuality: if exception occurs in Activate/Deactivate event handlers, our state would not
            // be corrupted because no internal state are affected by Activate/Deactivate. Please check Event handler exception continuality
            // if a state depending on those events is added.
            if (isActivated == true)
            {
                OnActivated(EventArgs.Empty);
            }
            else
            {
                OnDeactivated(EventArgs.Empty);
            }
            return false;
        }
 
        private bool WmQueryEndSession(IntPtr lParam, ref IntPtr refInt)
        {
            int reason = NativeMethods.IntPtrToInt32(lParam);
            bool retVal = false;
 
            // Event handler exception continuality: if exception occurs in SessionEnding event handlers, our state would not
            // be corrupted because no internal state are affected by SessionEnding. Please check Event handler exception continuality
            // if a state depending on this event is added.
            SessionEndingCancelEventArgs secEventArgs = new SessionEndingCancelEventArgs( (reason & NativeMethods.ENDSESSION_LOGOFF) != 0? ReasonSessionEnding.Logoff : ReasonSessionEnding.Shutdown );
            OnSessionEnding( secEventArgs );
 
            // shut down the app if not cancelled
            if ( secEventArgs.Cancel == false )
            {
                Shutdown();
                // return true to the wnd proc to signal that we can terminate properly
                refInt = new IntPtr(1);
                retVal = false;
            }
            else
            {
                refInt = IntPtr.Zero;
 
                // we have handled the event DefWndProc will not be called for this msg
                retVal = true;
            }
 
            return retVal;
        }
 
        private void InvalidateResourceReferenceOnWindowCollection(WindowCollection wc, ResourcesChangeInfo info)
        {
            bool hasImplicitStyles  = info.IsResourceAddOperation && HasImplicitStylesInResources;
 
            for (int i = 0; i < wc.Count; i++)
            {
                // calling thread is the same as the wc[i] thread so synchronously invalidate
                // resouces, else, post a dispatcher workitem to invalidate resources.
                if (wc[i].CheckAccess() == true)
                {
                    // Set the ShouldLookupImplicitStyles flag on the App's windows
                    // to true if App.Resources has implicit styles.
 
                    if (hasImplicitStyles)
                        wc[i].ShouldLookupImplicitStyles = true;
 
                    TreeWalkHelper.InvalidateOnResourcesChange(wc[i], null, info);
                }
                else
                {
                    wc[i].Dispatcher.BeginInvoke(
                        DispatcherPriority.Send,
                        (DispatcherOperationCallback) delegate(object obj)
                        {
                            object[] args = obj as object[];
 
                            // Set the ShouldLookupImplicitStyles flag on the App's windows
                            // to true if App.Resources has implicit styles.
 
                            if (hasImplicitStyles)
                                ((FrameworkElement)args[0]).ShouldLookupImplicitStyles = true;
 
                            TreeWalkHelper.InvalidateOnResourcesChange((FrameworkElement)args[0], null, (ResourcesChangeInfo)args[1]);
                            return null;
                        },
                        new object[] {wc[i], info}
                        );
                }
            }
        }
 
        private void SetExitCode(int exitCode)
        {
            if (_exitCode != exitCode)
            {
                _exitCode = exitCode;
                System.Environment.ExitCode = exitCode;
            }
        }
 
        private object ShutdownCallback(object arg)
        {
            ShutdownImpl();
            return null;
        }
        /// <summary>
        /// This method gets called on dispatch of the Shutdown DispatcherOperationCallback
        /// </summary>
        private void ShutdownImpl()
        {
            // Event handler exception continuality: if exception occurs in Exit event handler,
            // our cleanup action is to finish Shutdown since Exit cannot be cancelled. We don't
            // want user to use throw exception and catch it to cancel Shutdown.
            try
            {
                DoShutdown();
            }
            finally
            {
                // Quit the dispatcher if we ran our own.
                if (_ownDispatcherStarted == true)
                {
                    Dispatcher.CriticalInvokeShutdown();
                }
 
                ServiceProvider = null;
            }
        }
 
        private static bool IsValidShutdownMode(ShutdownMode value)
        {
            return value == ShutdownMode.OnExplicitShutdown
                || value == ShutdownMode.OnLastWindowClose
                || value == ShutdownMode.OnMainWindowClose;
        }
 
        private void OnPreBPReady(object sender, BPReadyEventArgs e)
        {
            NavService.PreBPReady -= new BPReadyEventHandler(OnPreBPReady);
            NavService.AllowWindowNavigation = false;
 
            ConfigAppWindowAndRootElement(e.Content, e.Uri);
 
            NavService = null;
            e.Cancel = true;
        }
 
        private void ConfigAppWindowAndRootElement(object root, Uri uri)
        {
            Window w = root as Window;
            if (w == null)
            {
                //Creates and returns a NavigationWindow for standalone cases
                //For browser hosted cases, returns the RootBrowserWindow precreated by docobjhost
                NavigationWindow appWin = GetAppWindow();
 
                //Since we cancel PreBPReady event here, the other navigation events won't fire twice.
                appWin.Navigate(root, new NavigateInfo(uri));
 
                // To avoid flash and re-layout, call Window.Show() asynchronously, at Normal priority, which
                // will happen right after navigation to the content completes.
                Dispatcher.BeginInvoke(DispatcherPriority.Normal,
                    new SendOrPostCallback((window) =>
                    {
                        if (!((Window)window).IsDisposed)
                        {
                            ((Window)window).Show();
                        }
                    }), appWin);
            }
            else
            {
                // if Visibility has not been set, we set it to true
                // Also check whether the window is already closed when we get here - applications could close the window
                // in its constructor.
                if (!w.IsVisibilitySet && !w.IsDisposed)
                {
                    w.Visibility = Visibility.Visible;
                }
            }
        }
 
 
        /// <summary>
        /// Plays a system sound using the PlaySound api.  This is a managed equivalent of the
        /// internet explorer method IEPlaySoundEx() from ieplaysound.cpp.
        /// </summary>
        /// <param name="soundName">The name of the sound to play</param>
        /// <returns>true if a sound was successfully played</returns>
        private void PlaySound(string soundName)
        {
            string soundFile = GetSystemSound(soundName);
 
            if (!string.IsNullOrEmpty(soundFile))
            {
                UnsafeNativeMethods.PlaySound(soundFile, IntPtr.Zero, PLAYSOUND_FLAGS);
            }
        }
 
        private string GetSystemSound(string soundName)
        {
            string soundFile = null;
            string regPath = $@"AppEvents\Schemes\Apps\Explorer\{soundName}\.current\";
            try
            {
                using (RegistryKey soundKey = Registry.CurrentUser.OpenSubKey(regPath))
                {
                    if (soundKey != null)
                    {
                        soundFile = (string)(soundKey.GetValue(""));
                    }
                }
            }
            // When the value of the register key is empty, the IndexOutofRangeException is thrown.
            // (Application.PlaySourd crash when the registry is broken)
            catch (System.IndexOutOfRangeException)
            {
            }
 
            return soundFile;
        }
 
        private EventHandlerList Events
        {
            get
            {
                if (_events == null)
                {
                    _events = new EventHandlerList();
                }
                return _events;
            }
        }
 
 
        //
        // Check if the current Uri is for the root element in a baml stream which is processed by an
        // outer LoadBaml.  such as it is through Navigate(uri) or LoadComoponent(uri).
        //
        private static bool IsComponentBeingLoadedFromOuterLoadBaml(Uri curComponentUri)
        {
            bool isRootElement = false;
 
            Invariant.Assert(curComponentUri != null, "curComponentUri should not be null");
 
            if (s_NestedBamlLoadInfo != null && s_NestedBamlLoadInfo.Count > 0)
            {
                //
                // Get the top LoadBamlSynInfo from the stack.
                //
                NestedBamlLoadInfo loadBamlSyncInfo = s_NestedBamlLoadInfo.Peek() as NestedBamlLoadInfo;
 
                if (loadBamlSyncInfo != null && loadBamlSyncInfo.BamlUri != null &&
                    loadBamlSyncInfo.BamlStream != null &&
                    BindUriHelper.DoSchemeAndHostMatch(loadBamlSyncInfo.BamlUri, curComponentUri))
                {
                    string fileInBamlConvert = loadBamlSyncInfo.BamlUri.LocalPath;
                    string fileCurrent = curComponentUri.LocalPath;
 
                    Invariant.Assert(fileInBamlConvert != null, "fileInBamlConvert should not be null");
                    Invariant.Assert(fileCurrent != null, "fileCurrent should not be null");
 
                    if (string.Equals(fileInBamlConvert, fileCurrent, StringComparison.OrdinalIgnoreCase))
                    {
                        //
                        // This is the root element of the xaml page which is being loaded to creat a tree
                        // through LoadBaml call by BamlConverter.
                        //
 
                        isRootElement = true;
                    }
                    else
                    {
                        // We consider Pack://application,,,/page1.xaml refers to the same component as
                        // Pack://application,,,/myapp;Component/page1.xaml.
                        string[] bamlConvertUriSegments = fileInBamlConvert.Split(new Char[] { '/', '\\' });
                        string[] curUriSegments = fileCurrent.Split(new Char[] { '/', '\\' });
 
                        int l = bamlConvertUriSegments.Length;
                        int m = curUriSegments.Length;
 
                        // The length of the segments should be at least 1, because the first one is empty.
                        Invariant.Assert((l >= 2) && (m >= 2));
 
                        int diff = l - m;
                        // The segment length can only be different in one for myapp;Component
                        if (Math.Abs(diff) == 1)
                        {
                            // Check whether the file name is the same.
                            if (string.Equals(bamlConvertUriSegments[l - 1], curUriSegments[m - 1], StringComparison.OrdinalIgnoreCase))
                            {
                                string component = (diff == 1) ? bamlConvertUriSegments[1] : curUriSegments[1];
 
                                isRootElement = BaseUriHelper.IsComponentEntryAssembly(component);
                            }
                        }
                    }
                }
            }
 
            return isRootElement;
        }
 
 
        private object RunDispatcher(object ignore)
        {
            if (_ownDispatcherStarted)
            {
                throw new InvalidOperationException(SR.ApplicationAlreadyRunning);
            }
            _ownDispatcherStarted = true;
            Dispatcher.Run();
            return null;
        }
 
        #endregion Private Methods
 
        //------------------------------------------------------
        //
        //  Private Fields
        //
        //------------------------------------------------------
 
        #region Private Fields
        static private object                           _globalLock;
        static private bool                             _isShuttingDown;
        static private bool                             _appCreatedInThisAppDomain;
        static private Application                      _appInstance;
        static private Assembly                         _resourceAssembly;
 
        // Keep LoadBamlSyncInfo stack so that the Outer LoadBaml and Inner LoadBaml( ) for the same
        // Uri share the related information.
        [ThreadStatic]
        private static Stack<NestedBamlLoadInfo> s_NestedBamlLoadInfo = null;
 
        private Uri                         _startupUri;
        private Uri                         _applicationMarkupBaseUri;
        private HybridDictionary            _htProps;
        private WindowCollection            _appWindowList;
        private WindowCollection            _nonAppWindowList;
        private Window                      _mainWindow;
        private ResourceDictionary          _resources;
 
        private bool                        _ownDispatcherStarted;
        private NavigationService           _navService;
 
        private ThemeMode                   _themeMode = ThemeMode.None;
        private bool                        _resourcesInitialized = false;
        private bool                        _reloadFluentDictionary = false;
 
        private MimeType                    _appMimeType;
        private IServiceProvider            _serviceProvider;
 
        private bool                        _appIsShutdown;
        private int                         _exitCode;
 
        private ShutdownMode                _shutdownMode = ShutdownMode.OnLastWindowClose;
 
        private HwndWrapper                 _parkingHwnd;
 
        private HwndWrapperHook             _appFilterHook;
 
        private EventHandlerList            _events;
        private bool                        _hasImplicitStylesInResources;
 
        private static readonly object EVENT_STARTUP = new object();
        private static readonly object EVENT_EXIT = new object();
        private static readonly object EVENT_SESSIONENDING = new object();
 
        private const SafeNativeMethods.PlaySoundFlags PLAYSOUND_FLAGS = SafeNativeMethods.PlaySoundFlags.SND_FILENAME |
                                                                            SafeNativeMethods.PlaySoundFlags.SND_NODEFAULT |
                                                                            SafeNativeMethods.PlaySoundFlags.SND_ASYNC |
                                                                            SafeNativeMethods.PlaySoundFlags.SND_NOSTOP;
        private const string SYSTEM_SOUNDS_REGISTRY_BASE                = @"HKEY_CURRENT_USER\AppEvents\Schemes\Apps\Explorer\";
        private const string SOUND_NAVIGATING                           = "Navigating";
        private const string SOUND_COMPLETE_NAVIGATION                  = "ActivatingDocument";
 
        #endregion Private Fields
 
        //------------------------------------------------------
        //
        //  Private Types
        //
        //------------------------------------------------------
        #region NavigationStateChange
        internal enum NavigationStateChange : byte
        {
            Navigating,
            Completed,
            Stopped,
        }
        #endregion NavigationStateChange
    }
 
    #endregion Application Class
 
 
    //
    // In Navigation(uri) and LoadComponent(uri), below scenarios might occur:
    //
    //   After a baml stream  is passed into LoadBaml( ) call, when instance
    //   of the root element is created, it would call the generated InitializeComponent( )
    //   which then calls LoadBaml( ) with the baml stream created from the same uri again.
    //
    // The LoadBaml( ) triggered by Navigation or LoadComponent(uri) is named as Outer LoadBaml.
    // The LoadBaml( ) called by IC in ctor of root Element is named as Inner LoadBaml.
    //
    // To prevent the baml stream created from the same Uri from being loaded twice, we need
    // a way to detect whether the Outer LoadBaml and Inner LoadBaml share the same share the
    // same stream and the same parser context.
    //
    internal class NestedBamlLoadInfo
    {
        //
        // ctor of NestedBamlLoadInfo
        //
        internal NestedBamlLoadInfo(Uri uri, Stream stream, bool bSkipJournalProperty)
        {
            _BamlUri = uri;
            _BamlStream = stream;
            _SkipJournaledProperties = bSkipJournalProperty;
        }
 
        #region internal properties
 
        //
        // OuterBamlUri property
        //
        internal Uri BamlUri
        {
            get { return _BamlUri;  }
            set { _BamlUri = value; }   // Code could reset the OuterBamlUri for performance optimization.
        }
 
        //
        // OuterBamlStream property
        //
        internal Stream BamlStream
        {
            get { return _BamlStream; }
        }
 
        //
        // OuterSkipJournaledProperties
        //
        internal bool SkipJournaledProperties
        {
            get { return _SkipJournaledProperties; }
        }
 
        #endregion
 
 
        #region private field
 
        // Keep Uri which is being handled by Outer LoadBaml in this thread.
        private Uri _BamlUri = null;
 
        // Keep the stream which is being handled by Outer LoadBaml for above Uri in this thread.
        private Stream _BamlStream = null;
 
        // Whether or not SkipJournalProperty when a baml stream is handled in Outer LoadBaml.
        private bool _SkipJournaledProperties = false;
 
        #endregion
    }
 
    #region enum ShutdownMode
 
    /// <summary>
    ///     Enum for ShutdownMode
    /// </summary>
    public enum ShutdownMode : byte
    {
        /// <summary>
        ///
        /// </summary>
        OnLastWindowClose = 0,
 
        /// <summary>
        ///
        /// </summary>
        OnMainWindowClose = 1,
 
        /// <summary>
        ///
        /// </summary>
        OnExplicitShutdown
 
        // NOTE: if you add or remove any values in this enum, be sure to update Application.IsValidShutdownMode()
    }
 
    #endregion enum ShutdownMode
 
    #region enum ReasonSessionEnding
 
    /// <summary>
    ///     Enum for ReasonSessionEnding
    /// </summary>
    public enum ReasonSessionEnding : byte
    {
        /// <summary>
        ///
        /// </summary>
        Logoff = 0,
        /// <summary>
        ///
        /// </summary>
        Shutdown
    }
    #endregion enum ReasonSessionEnding
}