// NTRAID#Windows Out Of Band Releases-915506-2005/09/09 // Removed HandleUnexpectedExceptions infrastructure /// <summary> /// /// internal Entry point in msh console host implementation /// /// </summary> /// /// <param name="configuration"> /// Configuration information to use for creating runspace. /// </param> /// /// <param name="bannerText"> /// Banner text to be displayed by ConsoleHost /// </param> /// /// <param name="helpText"> /// Help text for minishell. This is displayed on 'minishell -?'. /// </param> /// /// <param name="preStartWarning"> /// /// Warning occurred prior to this point, for example, a snap-in fails to load beforehand. /// This string will be printed out. /// /// </param> /// <param name = "args"> /// /// Command line parameters to powershell.exe /// /// </param> /// <returns> /// /// The exit code for the shell. /// /// NTRAID#Windows OS Bugs-1036968-2005/01/20-sburns The behavior here is related to monitor work. The low word of the /// exit code is available for the user. The high word is reserved for the shell and monitor. /// /// The shell process needs to return: /// /// - if the shell.exe fails init, 0xFFFF0000 /// - if the exit keyword is called with no parameter at the point of top-level prompt, 0x80000000 (e.g. 0 with the high /// bit set) /// - if the exit keyword is called with any int param less than or equal to 0xFFFF, then that int masked with the high /// bit set. e.g. "exit 3" results in 0x80000003 /// - if the script ends (in the case of msh -command or msh -commandfile), then 0x80000000. /// - if ctrl-break is pressed, with 0xFFFE0000 /// - if the shell.exe is passed a bad command-line parameter, with 0xFFFD0000. /// - if the shell.exe crashes, with 0x00000000 /// /// The monitor process gets the exit code. If the high bit is set, then the shell process exited normally (though /// possibly due to an error). If not, the shell process crashed. If the shell.exe exit code is x00000000 (crashed) /// or 0xFFFE0000 (user hit ctrl-break), the monitor should restart the shell.exe. Otherwise, the monitor should exit /// with the same exit code as the shell.exe. /// /// Anyone checking the exit code of the shell or monitor can mask off the hiword to determine the exit code passed /// by the script that the shell last executed. /// /// </returns> internal static int Start( RunspaceConfiguration configuration, string bannerText, string helpText, string preStartWarning, string[] args) { #if DEBUG if (Environment.GetEnvironmentVariable("POWERSHELL_DEBUG_STARTUP") != null) { while (!System.Diagnostics.Debugger.IsAttached) { Thread.Sleep(1000); } } #endif try { string profileDir; #if UNIX profileDir = Platform.SelectProductNameForDirectory(Platform.XDG_Type.CACHE); #else profileDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Microsoft\Windows\PowerShell"; if (!Directory.Exists(profileDir)) { Directory.CreateDirectory(profileDir); } #endif ClrFacade.SetProfileOptimizationRoot(profileDir); } catch { // It's safe to ignore errors, the guarded code is just there to try and // improve startup performance. } uint exitCode = ExitCodeSuccess; System.Threading.Thread.CurrentThread.Name = "ConsoleHost main thread"; s_theConsoleHost = ConsoleHost.CreateSingletonInstance(configuration); s_theConsoleHost.BindBreakHandler(); PSHost.IsStdOutputRedirected = Console.IsOutputRedirected; if (args == null) { args = new string[0]; } if (!string.IsNullOrEmpty(preStartWarning)) { s_theConsoleHost.UI.WriteWarningLine(preStartWarning); } try { s_cpp = new CommandLineParameterParser(s_theConsoleHost, s_theConsoleHost._ver, bannerText, helpText); string[] tempArgs = new string[args.GetLength(0)]; args.CopyTo(tempArgs, 0); s_cpp.Parse(tempArgs); // Servermode parameter validation check. if ((s_cpp.ServerMode && s_cpp.NamedPipeServerMode) || (s_cpp.ServerMode && s_cpp.SocketServerMode) || (s_cpp.NamedPipeServerMode && s_cpp.SocketServerMode)) { s_tracer.TraceError("Conflicting server mode parameters, parameters must be used exclusively."); s_theConsoleHost.ui.WriteErrorLine(ConsoleHostStrings.ConflictingServerModeParameters); unchecked { return (int)ExitCodeBadCommandLineParameter; } } if (s_cpp.ServerMode) { ClrFacade.StartProfileOptimization("StartupProfileData-ServerMode"); System.Management.Automation.Remoting.Server.OutOfProcessMediator.Run(s_cpp.InitialCommand); exitCode = 0; } else if (s_cpp.NamedPipeServerMode) { ClrFacade.StartProfileOptimization("StartupProfileData-NamedPipeServerMode"); System.Management.Automation.Remoting.RemoteSessionNamedPipeServer.RunServerMode( s_cpp.ConfigurationName); exitCode = 0; } else if (s_cpp.SSHServerMode) { ClrFacade.StartProfileOptimization("StartupProfileData-SSHServerMode"); System.Management.Automation.Remoting.Server.SSHProcessMediator.Run(s_cpp.InitialCommand); exitCode = 0; } else if (s_cpp.SocketServerMode) { ClrFacade.StartProfileOptimization("StartupProfileData-SocketServerMode"); System.Management.Automation.Remoting.Server.HyperVSocketMediator.Run(s_cpp.InitialCommand, s_cpp.ConfigurationName); exitCode = 0; } else { ClrFacade.StartProfileOptimization( s_theConsoleHost.LoadPSReadline() ? "StartupProfileData-Interactive" : "StartupProfileData-NonInteractive"); exitCode = s_theConsoleHost.Run(s_cpp, !string.IsNullOrEmpty(preStartWarning)); } } finally { TelemetryAPI.ReportExitTelemetry(s_theConsoleHost); s_theConsoleHost.Dispose(); } unchecked { return (int)exitCode; } }
private uint Run(string bannerText, string helpText, bool isPrestartWarned, string[] args) { s_cpp = new CommandLineParameterParser(this, _ver, bannerText, helpText); s_cpp.Parse(args); return Run(s_cpp, isPrestartWarned); }