예제 #1
0
        protected string RenderScriptValue(PSObject inputObject,
                                           ScriptBlock script,
                                           bool dontGroupMultipleResults)
        {
            // Let the script also use context created by the custom header script (if any).
            if (m_preservedScriptContext != null)
            {
                script = m_preservedScriptContext.NewBoundScriptBlock(script);
            }

#if DEBUG
            sm_renderScriptCallDepth++;
            if (sm_renderScriptCallDepth > 10)
            {
                // Helps to catch runaway rendering /before/ gobbling tons of memory
                System.Diagnostics.Debugger.Break();
                // Maybe I should just throw?
            }
#endif


            using (DbgProvider.LeaseShell(out PowerShell shell))
            {
                //
                // script.InvokeWithContext is a lot nicer-looking. But the problem with
                // it is that non-terminating errors don't go to the output or an easily
                // checked buffer, and I'd prefer that no errors get hidden. Strangely,
                // calling script.InvokeWithContext directly in
                // InvokeScriptCommand.InvokeWithContext does send the errors down the
                // pipeline to be displayed. I don't know what is making the difference.
                //
                // Things to try with both methods:
                //
                //      $ctx = $null
                //      $savedCtx = $null
                //      Invoke-Script -ScriptBlock { "hi" ; Write-Error "non-term" ; "bye" } -WithContext $ctx
                //
                //      { "hi" ; Write-Error "non-term" ; "bye" }.InvokeWithContext( @{}, @() )
                //
                //      $tmpMod = New-Module { }
                //      $scriptBlockWithDifferentExecCtx = & $tmpMod { { "hi" ; Write-Error "non-term" ; "bye" } }
                //      $scriptBlockWithDifferentExecCtx.InvokeWithContext( @{}, @() )
                //
                //      Register-AltTypeFormatEntries { New-AltTypeFormatEntry -TypeName 'System.Int32' { New-AltCustomViewDefinition { "It's an int: $_" ; Write-Error "this is non-terminating" ; "done" } } }
                //      42
                //
                Collection <PSObject> results;

                try
                {
                    // Note that StrictMode will be enforced for value converters, because
                    // they execute in the scope of Debugger.Formatting.psm1, which sets
                    // StrictMode.
                    InvokeCommand.InvokeScript(false, sm_pipeIndexScript, null, m_pipeIndex);
                    var info = InvokeCommand.GetCmdlet("ForEach-Object");
                    shell.AddCommand(info).AddParameter("Process", script);
                    results = shell.Invoke(new[] { inputObject });
                }
                catch (RuntimeException e)
                {
                    // Make the error available for inspection:
                    AddToError(Util.FixErrorRecord(e.ErrorRecord, e));

                    return(new ColorString(ConsoleColor.Red,
                                           Util.Sprintf("<Error: {0}>", e))
                           .ToString(DbgProvider.HostSupportsColor));
                }

#if DEBUG
                sm_renderScriptCallDepth--;
#endif

                // For some reason, sometimes shell.HadErrors returns true when
                // shell.Streams.Error.Count is 0, when the pipeline is stopping.
                if (Stopping)
                {
                    return(String.Empty);
                }

                // INT2d518c4b: shell.HadErrors is clueless.
                //if( shell.HadErrors )
                if (shell.Streams.Error.Count > 0)
                {
                    // (don't need to call AddToError explicitly; they will already be
                    // available in $error)

                    if (1 == shell.Streams.Error.Count)
                    {
                        return(new ColorString(ConsoleColor.Red,
                                               Util.Sprintf("<Error: {0}>",
                                                            shell.Streams.Error[0]))
                               .ToString(DbgProvider.HostSupportsColor));
                    }
                    else
                    {
                        return(new ColorString(ConsoleColor.Red,
                                               Util.Sprintf("<Multiple errors ({0}) encountered>",
                                                            shell.Streams.Error.Count))
                               .ToString(DbgProvider.HostSupportsColor));
                    }
                }
                else
                {
                    if ((null == results) || (0 == results.Count))
                    {
                        return(null);
                    }

                    return(ObjectsToMarkedUpString(results,
                                                   "{0}",  // <-- IMPORTANT: this prevents infinite recursion via Format-AltSingleLine
                                                   null,
                                                   dontGroupMultipleResults).ToString());
                } // end else( no errors )
            }     // end using( shell lease )
        }         // end RenderScriptValue()