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()