internal CommandLineParameterParser(ColorConsoleHost p, /*Version ver,*/ string bannerText, string helpText)
        {
            Util.Assert(p != null, "parent ColorConsoleHost must be supplied");

            this.bannerText = bannerText;
            this.helpText   = helpText;
            this.parent     = p;
            this.ui         = (ColorHostUserInterface)p.UI;
            // this.ver = ver;
        }
        } // end _AltMainThread()

        static int MainWorker(string[] args)
        {
            try
            {
                var profileDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData,
                                                                        Environment.SpecialFolderOption.DoNotVerify),
                                              "Temp",
                                              "DbgProvider",
                                              "ProfileOpt");
                Directory.CreateDirectory(profileDir);

                System.Runtime.ProfileOptimization.SetProfileRoot(profileDir);

                System.Runtime.ProfileOptimization.StartProfile("StartupProfileData-" +
                                                                (DbgProvider.IsInGuestMode ? "GuestMode"
                                                                                            : "NormalMode"));
            }
            catch
            {
                Util.Fail("SetProfileRoot/StartProfile failed");
                // It's safe to ignore errors, the guarded code is just there to try and
                // improve startup performance.
            }

            string rootDir;

            try
            {
                rootDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception! {0}", e);
                return(-1);
            }

            //Console.WriteLine( "rootDir: {0}", rootDir );

            /*
             * string pathToMsvcr120 = Assembly.GetExecutingAssembly().Location;
             * pathToMsvcr120 = Path.GetDirectoryName( pathToMsvcr120 );
             #if DEBUG
             * pathToMsvcr120 = Path.Combine( pathToMsvcr120, "Debugger", "MSVCR120d.dll" );
             #else
             * pathToMsvcr120 = Path.Combine( pathToMsvcr120, "Debugger", "MSVCR120.dll" );
             #endif
             *
             * IntPtr hMsvcr = NativeMethods.LoadLibraryEx( pathToMsvcr120,
             *                                            IntPtr.Zero,
             *                                            LoadLibraryExFlags.LOAD_WITH_ALTERED_SEARCH_PATH );
             * if( IntPtr.Zero == hMsvcr )
             *  throw new Exception( "Could not load MSVCR120.dll." );
             */


            _ConfigureModulePath(rootDir);

            _RemoveMarkOfTheInternet(rootDir);

            string dbgModuleDir = Path.Combine(rootDir, "Debugger");


            // TODO: investigate differences between CreateDefault and CreateDefault2
            InitialSessionState iss = InitialSessionState.CreateDefault();

            iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Bypass;

            // TODO: maybe add to iss.Formats?

            List <InitScript> initScripts = new List <InitScript>();


            initScripts.Add(new InitScript("SetStrictMode",
                                           "Set-StrictMode -Version Latest"));

            initScripts.Add(new InitScript("ImportOurModule",
                                           Util.Sprintf(@"Import-Module ""{0}""",
                                                        Path.Combine(dbgModuleDir, "Debugger.psd1"))));

            initScripts.Add(new InitScript("CreateBinDrive",
                                           String.Format(CultureInfo.InvariantCulture,
                                                         @"[void] (New-PSDrive Bin FileSystem ""{0}"")",
                                                         rootDir)));

            initScripts.Add(new InitScript("SetStartLocation", "Set-Location Dbg:\\"));

            if (DbgProvider.IsInGuestMode)
            {
                // In guest mode, we are already attached to something, so we need to
                // build the namespace based on the existing dbgeng state.
                initScripts.Add(new InitScript("RebuildNs",
                                               "[MS.Dbg.DbgProvider]::ForceRebuildNamespace()"));
            }

            // I cannot explain why, but using Update-FormatData (which is [a proxy
            // function] defined in our module instead of Invoke-Script (a C# cmdlet
            // defined in our module) subtly changes something having to do with scope or
            // something, such that the $AltListIndent variable wasn't working... until
            // all the format data was reloaded via Update-FormatData.
            var fmtScripts = _GetFmtScripts(dbgModuleDir);

            initScripts.Add(
                new InitScript("LoadFmtDefinitions",
                               String.Format(CultureInfo.InvariantCulture,
                                             @"[void] (Update-FormatData ""{0}"")",
                                             String.Join("\", \"", fmtScripts))));

            // And in fact it seems that the trick to not losing our "captured contexts"
            // is that Update-AltFormatData needs to always be run in the context of the
            // Debugger.Formatting module.
            string monkeyPatched = @"function Update-AltFormatData {
    [CmdletBinding()]
    param( [Parameter( Mandatory = $false )]
           [string[]] $AppendPath = @(),

           [Parameter( Mandatory = $false )]
           [string[]] $PrependPath = @()
         )

    process
    {
        try
        {
            # This is pretty ugly. In particular, I can't find a better way to pass in
            # -Verbose. Ideally it could just be captured magically, but things like
            # <scriptblock>.GetNewClosure() don't seem to help.

            Invoke-InAlternateScope -ScriptBlock { $VerbosePreference = $args[2] ; Debugger\Update-AltFormatData -AppendPath $args[0] -PrependPath $args[1] } `
                                    -Arguments @( $AppendPath, $PrependPath, $VerbosePreference ) `
                                    -ScopingModule ((Get-Module Debugger).NestedModules | where name -eq 'Debugger.Formatting')
        }
        finally { }
    } # end 'process' block
<#
.ForwardHelpTargetName Update-AltFormatData
.ForwardHelpCategory Cmdlet
#>
}";

            initScripts.Add(new InitScript("MonkeyPatchUpdateAltFormatData",
                                           monkeyPatched));


            string typesPs1Xml = Path.Combine(dbgModuleDir, "Types.ps1xml");

            if (File.Exists(typesPs1Xml))    // TODO: Remove once types.ps1xml is picked in
            {
                initScripts.Add(
                    new InitScript("LoadTypeAdapterStuff",
                                   String.Format(CultureInfo.InvariantCulture,
                                                 @"[void] (Update-TypeData ""{0}"")",
                                                 c_FileSystem_PowerShellProviderPrefix + typesPs1Xml)));
            }

            var           converterScripts  = Directory.GetFiles(dbgModuleDir, "Debugger.Converters.*.ps1");
            StringBuilder loadConvertersCmd = new StringBuilder();

            foreach (var converterScript in converterScripts)
            {
                loadConvertersCmd.Append(Util.Sprintf("; [void] (& '{0}{1}')", c_FileSystem_PowerShellProviderPrefix, converterScript));
            }

            string argCompleterScript = Path.Combine(dbgModuleDir, "Debugger.ArgumentCompleters.ps1");

            loadConvertersCmd.Append(Util.Sprintf("; [void] (& '{0}{1}')", c_FileSystem_PowerShellProviderPrefix, argCompleterScript));

            initScripts.Add(new InitScript("LoadConverters",
                                           loadConvertersCmd.ToString()));

            // TODO: wrap
            var colorBanner = new ColorString(ConsoleColor.Cyan, "Microsoft Debugger DbgShell\n")
                              .AppendFg(ConsoleColor.DarkCyan).Append("Copyright (c) 2015\n\n")
                              .AppendFg(ConsoleColor.Magenta).Append("Welcome.\n\n")
                              .AppendFg(ConsoleColor.Gray).Append("Note that script execution policy is '")
                              .AppendFg(ConsoleColor.Yellow).Append("Bypass")
                              .AppendFg(ConsoleColor.Gray).Append("' for this process.\nRun '")
                              .AppendFg(ConsoleColor.Yellow).Append("Get-Help")
                              .AppendFg(ConsoleColor.Gray).Append(" about_DbgShell_GettingStarted' to learn about DbgShell.\n");

            if (DbgProvider.IsInGuestMode)
            {
                colorBanner
                .AppendFg(ConsoleColor.Gray).Append("\nWhen you are finished here and want to return control back to the debugger, run '")
                .AppendFg(ConsoleColor.Yellow).Append("q")
                .AppendFg(ConsoleColor.Gray).Append("' or '")
                .AppendFg(ConsoleColor.Green).Append("exit")
                .AppendFg(ConsoleColor.Gray).Append("'.");
            }

            string banner = colorBanner.ToString(true);

            int rc = ColorConsoleHost.Start(iss,
                                            initScripts,
                                            banner,
                                            String.Empty,
                                            args);

            return(rc);
        } // end MainWorker()
        private static int _GuestModeMainWrapper(ExceptionGuard entryPointStateDisposer,
                                                 string[] args)
        {
            // We should have two things:
            //    args[ 0 ]: either "consoleOwner" or "shareConsole" (windbg versus ntsd, for instance)
            //    args[ 1 ]: command args should all should get passed in one big string.
            Util.Assert(2 == args.Length);

            bool shareConsole = false;

            if (0 == StringComparer.Ordinal.Compare(args[0], c_guestModeShareConsole))
            {
                shareConsole = true;
            }
            else
            {
                if (0 != StringComparer.Ordinal.Compare(args[0], c_guestModeConsoleOwner))
                {
                    var msg = "Unexpected arg: I expected to see \"consoleOwner\".";
                    Util.Fail(msg);
                    throw new Exception(msg);
                }
            }

            bool firstTime      = null == sm_altMainThread;
            bool alreadyRunning = DbgProvider.EntryDepth > 1;

            try
            {
                bool   noProfile;
                bool   inBreakpointCommand;
                string command = _ParseGuestModeArgs(args[1],
                                                     firstTime,
                                                     out noProfile,
                                                     out inBreakpointCommand);

                if (inBreakpointCommand && !DbgProvider.IsInBreakpointCommand)
                {
                    DbgProvider.IsInBreakpointCommand = true;
                    entryPointStateDisposer.Protect((Disposable)(() => DbgProvider.IsInBreakpointCommand = false));
                }

                if (firstTime)
                {
                    Util.Assert(!alreadyRunning);
                    ColorConsoleHost.GuestModeInjectCommand(command);

                    LogManager.Trace("_GuestModeMainWrapper: initial entry.");
                    // This is the first time we've been run, so we need to start everything
                    // up, pretty much the same as when running as a normal EXE.
                    sm_altMainThread = new Thread(_AltMainThread);

                    DbgProvider.SetGuestMode(shareConsole);

                    string[] mainArgs = null;
                    if (noProfile)
                    {
                        mainArgs = new string[] { "-NoProfile" }
                    }
                    ;

                    sm_altMainThread.Start(mainArgs);

                    // This will get signaled when things have been initialized enough to
                    // where we can start the guest mode thread activity.
                    DbgProvider.GuestModeEvent.WaitOne();
                    DbgProvider.GuestModeEvent.Reset();
                }
                else
                {
                    if (alreadyRunning)
                    {
                        // Re-entrant case: DbgShell is already running, but something called
                        // the debugger "!dbgshell" extension command (for instance, a
                        // breakpoint command).
                        LogManager.Trace("_GuestModeMainWrapper: re-entering (entryDepth: {0}).", DbgProvider.EntryDepth);
                        if (null == DbgProvider.CurrentActionQueue)
                        {
                            Util.Fail("DbgShell is already running, but I don't have a CurrentActionQueue to inject commands.");
                            throw new Exception("DbgShell is already running, but I don't have a CurrentActionQueue to inject commands.");
                        }
                        var transferTicket = entryPointStateDisposer.Transfer();
                        DbgProvider.CurrentActionQueue.PostCommand((cii) =>
                        {
                            using (transferTicket.Redeem())
                            {
                                LogManager.Trace("Executing injected (reentrant) commands:");
                                LogManager.Trace(command.Replace("\n", "\n > "));
                                cii.InvokeScript(command,
                                                 false,
                                                 PipelineResultTypes.Error |
                                                 PipelineResultTypes.Output,
                                                 sm_noInput);
                            }     // end using( new disposer )
                        });
                        transferTicket.CommitTransfer();
                    }
                    else
                    {
                        LogManager.Trace("_GuestModeMainWrapper: resuming.");
                        ColorConsoleHost.GuestModeInjectCommand(command);

                        // We already have an alternate main thread, which is "paused" (blocked),
                        // waiting to resume.

                        DbgProvider.GuestModeResume();
                    }
                }

                if (!alreadyRunning)
                {
                    LogManager.Trace("_GuestModeMainWrapper: entering GuestModeGuestThreadActivity.");
                    // The guest mode thread activity is to pump the DbgEngThread (this thread is
                    // the thread that the debugger extension was called on, and we need to use
                    // this thread to interact with dbgeng).
                    //
                    // (if alreadyRunning, then we are already running the
                    // GuestModeGuestThreadActivity (it's below us on the stack))
                    DbgProvider.GuestModeGuestThreadActivity();
                }

                LogManager.Trace("_GuestModeMainWrapper: returning {0}.",
                                 Util.FormatErrorCode(sm_exitCode));
                return(sm_exitCode);
            }
            finally
            {
                LogManager.Trace("_GuestModeMainWrapper: leaving.");
            }
        } // end _GuestModeMainWrapper()