private void Shutdown()
        {
            this.UnsubscribeSnoopUiEvents();

            this.ProviderLocationChanged -= this.OnProviderLocationChanged;

            this.host = null;

            this.runspace?.Dispose();
            this.runspace = null;

            this.isStarted = false;
        }
        /// <summary>
        /// Initiates the startup routine and configures the runspace for use.
        /// </summary>
        private void Start(SnoopUI snoopUi)
        {
            if (this.isStarted)
            {
                return;
            }

            if (ShellConstants.IsPowerShellInstalled == false)
            {
                return;
            }

            this.isStarted = true;

            this.snoopUi = snoopUi;

            {
                // ignore execution-policy
                var iis = InitialSessionState.CreateDefault();
                iis.AuthorizationManager = new AuthorizationManager(Guid.NewGuid().ToString());
                iis.Providers.Add(new SessionStateProviderEntry(ShellConstants.DriveName, typeof(VisualTreeProvider), string.Empty));

                this.host     = new SnoopPSHost(this.outputTextBox, x => this.outputTextBox.AppendText(x));
                this.runspace = RunspaceFactory.CreateRunspace(this.host, iis);
                this.runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;

#if NET40
                this.runspace.ApartmentState = System.Threading.ApartmentState.STA;
#endif

                this.runspace.Open();
            }

            {
                snoopUi.PropertyChanged += this.OnSnoopUiOnPropertyChanged;

                // allow scripting of the host controls
                this.SetVariable("snoopui", snoopUi);
                this.SetVariable("ui", this);
                this.SetVariable(ShellConstants.Root, snoopUi.Root);
                this.SetVariable(ShellConstants.Selected, snoopUi.CurrentSelection);

                // marshall back to the UI thread when the provider notifiers of a location change
                var action = new Action <TreeItem>(item => this.RunInDispatcherAsync(() => this.ProviderLocationChanged?.Invoke(item)));
                this.SetVariable(ShellConstants.LocationChangedActionKey, action);

                var folder = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "..", "Scripts");
                this.Invoke($"import-module \"{Path.Combine(folder, ShellConstants.SnoopModule)}\"");

                this.outputTextBox.Clear();

                this.Invoke("write-host 'Welcome to the Snoop PowerShell console!'");
                this.Invoke("write-host '----------------------------------------'");
                this.Invoke($"write-host 'To get started, try using the ${ShellConstants.Root} and ${ShellConstants.Selected} variables.'");

                this.FindAndLoadProfile(folder);

                this.NotifySelected(snoopUi.CurrentSelection);
            }

            {
                // sync the current location
                snoopUi.Tree.SelectedItemChanged += this.OnSnoopUiSelectedItemChanged;
                this.ProviderLocationChanged     += this.OnProviderLocationChanged;

                // clean up garbage!
                snoopUi.Closed += this.OnSnoopUiClosed;
            }
        }