// We have separate argument parsing for guest mode. // // There are a few reasons: // * The arguments for the standalone EXE and the arguments for guest mode // don't necessarily match (we don't need -File for guest mode, we want to // let people just type a command instead of having to type "-Command" first, // -ReadFromStdin doesn't make sense, etc.) // * The "normal mode" argument parsing happens on a code path that is only run // once in guest mode, the first time !dbgshell is run. Of course it would be // possible to change that, but I'm trying to minimize the amount of churn // caused by introducing guest mode. private static string _ParseGuestModeArgs(string line, bool firstTime, out bool noProfile, out bool inBreakpointCommand) { line = line.Trim(); bool noExit = false; bool isEncoded = false; noProfile = false; inBreakpointCommand = false; StringBuilder sbCmd = new StringBuilder(line.Length * 2); sbCmd.AppendLine("try {"); // I think we shouldn't need "-File", because both execution operators seem to // work fine: // // !dbgshell & D:\blah\foo.ps1 // !dbgshell . D:\blah\foo.ps1 // int idx = 0; while (idx < line.Length) { // Eat space. while ((idx < line.Length) && ((line[idx] == ' ') || (line[idx] == '\t'))) { idx++; } if (idx >= line.Length) { break; } if ((line[idx] == '/') || (line[idx] == '-')) { idx++; int idxSpace = line.IndexOfAny(sm_delims, idx); if (idxSpace < 0) { idxSpace = line.Length; } string opt = line.Substring(idx, (idxSpace - idx)); if (0 == opt.Length) { // Just a "- "? idx++; continue; } if ("NoExit".StartsWith(opt, StringComparison.OrdinalIgnoreCase)) { noExit = true; } else if ("NoProfile".StartsWith(opt, StringComparison.OrdinalIgnoreCase)) { noProfile = true; } else if ("EncodedCommand".StartsWith(opt, StringComparison.OrdinalIgnoreCase)) { isEncoded = true; idx = idx + opt.Length; break; } else if ("Bp".StartsWith(opt, StringComparison.OrdinalIgnoreCase)) { inBreakpointCommand = true; // When we hit a breakpoint, we could be on a different thread. sbCmd.AppendLine("[MS.Dbg.DbgProvider]::SetLocationByDebuggerContext()"); } else { sbCmd.AppendLine(Util.Sprintf("Write-Error 'Unexpected option: ''-{0}''.'", opt)); } idx = idx + opt.Length; } // end if( it's an option ) else { // Done with options. break; } } // end while( idx < line.Length ) if (noProfile && !firstTime) { sbCmd.AppendLine("Write-Warning '-NoProfile only works when used with the first invocation of !dbgshell.'"); sbCmd.AppendLine("Write-Warning 'You can unload and reload DbgShellExt, and then run \"!dbgshell -NoProfile\".'"); } if (isEncoded) { string encoded = line.Substring(idx).Trim(); if (0 == encoded.Length) { sbCmd.AppendLine("Write-Warning \"Encoded command was empty.\""); } else { sbCmd.AppendLine(DbgProvider.DecodeString(encoded)); } } else { if (idx < line.Length) { sbCmd.AppendLine(line.Substring(idx)); } else { // No command implies we want the shell to stick around so we can use it // interactively. noExit = true; } } bool reentering = DbgProvider.EntryDepth > 1; if (!noExit && !reentering) { sbCmd.AppendLine("exit"); } else if (noExit && reentering) { sbCmd.AppendLine("Write-Warning 'N.B. There is already a running pipeline--you are now in a nested prompt.'"); sbCmd.AppendLine("$Host.EnterNestedPrompt()"); } sbCmd.AppendLine("} finally { }"); return(sbCmd.ToString()); } // end _ParseGuestModeArgs()
private bool ParseCommand(string[] args, ref int i, bool noexitSeen, bool isEncoded) { if (commandLineCommand != null) { // we've already set the command, so squawk //ui.WriteErrorLine(CommandLineParameterParserStrings.CommandAlreadySpecified); ui.WriteErrorLine("Hey wait; there's already a command!"); showHelp = true; abortStartup = true; exitCode = ExitCodeBadCommandLineParameter; return(false); } ++i; if (i >= args.Length) { //ui.WriteErrorLine(CommandLineParameterParserStrings.MissingCommandParameter); ui.WriteErrorLine("Missing command."); showHelp = true; abortStartup = true; exitCode = ExitCodeBadCommandLineParameter; return(false); } if (isEncoded) { try { //commandLineCommand = StringToBase64Converter.Base64ToString(args[i]); //commandLineCommand = Encoding.Unicode.GetString( Convert.FromBase64String( args[ i ] ) ); commandLineCommand = DbgProvider.DecodeString(args[i]); } // decoding failed catch { //ui.WriteErrorLine(CommandLineParameterParserStrings.BadCommandValue); ui.WriteErrorLine("Bad command value."); showHelp = true; abortStartup = true; exitCode = ExitCodeBadCommandLineParameter; return(false); } } else if (args[i] == "-") { // the arg to -command is -, which is secret code for "read the commands from stdin with no prompts" readFromStdin = true; noPrompt = true; ++i; if (i != args.Length) { // there are more parameters to -command than -, which is an error. //ui.WriteErrorLine(CommandLineParameterParserStrings.TooManyParametersToCommand); ui.WriteErrorLine("Too many parameters for command."); showHelp = true; abortStartup = true; exitCode = ExitCodeBadCommandLineParameter; return(false); } if (!parent.IsStandardInputRedirected) { //ui.WriteErrorLine(CommandLineParameterParserStrings.StdinNotRedirected); ui.WriteErrorLine("StdIn not redirected."); showHelp = true; abortStartup = true; exitCode = ExitCodeBadCommandLineParameter; return(false); } } else { // Collect the remaining parameters and combine them into a single command to be run. StringBuilder cmdLineCmdSB = new StringBuilder(); while (i < args.Length) { cmdLineCmdSB.Append(args[i] + " "); ++i; } if (cmdLineCmdSB.Length > 0) { // remove the last blank cmdLineCmdSB.Remove(cmdLineCmdSB.Length - 1, 1); } commandLineCommand = cmdLineCmdSB.ToString(); } if (!noexitSeen) { // don't reset this if they've already specified -noexit noExit = false; } showBanner = false; return(true); }