public PowerShellExecutionResults run_host(ChocolateyConfiguration config, string chocoPowerShellScript, Action <Pipeline> additionalActionsBeforeScript)
        {
            // since we control output in the host, always set these true
            Environment.SetEnvironmentVariable("ChocolateyEnvironmentDebug", "true");
            Environment.SetEnvironmentVariable("ChocolateyEnvironmentVerbose", "true");

            var    result       = new PowerShellExecutionResults();
            string commandToRun = wrap_script_with_module(chocoPowerShellScript, config);
            var    host         = new PoshHost(config);

            this.Log().Debug(() => "Calling built-in PowerShell host with ['{0}']".format_with(commandToRun.escape_curly_braces()));

            var initialSessionState = InitialSessionState.CreateDefault();

            // override system execution policy without accidentally setting it
            initialSessionState.AuthorizationManager = new AuthorizationManager("choco");
            using (var runspace = RunspaceFactory.CreateRunspace(host, initialSessionState))
            {
                runspace.Open();

                // this will affect actual execution policy
                //RunspaceInvoke invoker = new RunspaceInvoke(runspace);
                //invoker.Invoke("Set-ExecutionPolicy ByPass");

                using (var pipeline = runspace.CreatePipeline())
                {
                    // The powershell host itself handles the following items:
                    // * Write-Debug
                    // * Write-Host
                    // * Write-Verbose
                    // * Write-Warning
                    //
                    // the two methods below will pick up Write-Output and Write-Error

                    // Write-Output
                    pipeline.Output.DataReady += (sender, args) =>
                    {
                        PipelineReader <PSObject> reader = sender as PipelineReader <PSObject>;

                        if (reader != null)
                        {
                            while (reader.Count > 0)
                            {
                                host.UI.WriteLine(reader.Read().to_string().escape_curly_braces());
                            }
                        }
                    };

                    // Write-Error
                    pipeline.Error.DataReady += (sender, args) =>
                    {
                        PipelineReader <object> reader = sender as PipelineReader <object>;

                        if (reader != null)
                        {
                            while (reader.Count > 0)
                            {
                                host.UI.WriteErrorLine(reader.Read().to_string().escape_curly_braces());
                            }
                        }
                    };

                    var documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments, Environment.SpecialFolderOption.DoNotVerify);
                    var currentUserCurrentHostProfile = _fileSystem.combine_paths(documentsFolder, "WindowsPowerShell\\Microsoft.PowerShell_profile.ps1");
                    var recreateProfileScript         = @"
if ((Test-Path(""{0}"")) -and ($profile -eq $null -or $profile -eq '')) {{
  $global:profile = ""{1}""
}}
".format_with(documentsFolder, currentUserCurrentHostProfile);

                    pipeline.Commands.Add(new Command(recreateProfileScript, isScript: true, useLocalScope: false));

                    // The PowerShell Output Redirection bug affects System.Management.Automation
                    // it appears with v3 more than others. It is already known to affect v2
                    // this implements the redirection fix from the post below, fixed up with some comments
                    // http://www.leeholmes.com/blog/2008/07/30/workaround-the-os-handles-position-is-not-what-filestream-expected/
                    const string outputRedirectionFixScript = @"
try {
  $bindingFlags = [Reflection.BindingFlags] ""Instance,NonPublic,GetField""
  $objectRef = $host.GetType().GetField(""externalHostRef"", $bindingFlags).GetValue($host)
  $bindingFlags = [Reflection.BindingFlags] ""Instance,NonPublic,GetProperty""
  $consoleHost = $objectRef.GetType().GetProperty(""Value"", $bindingFlags).GetValue($objectRef, @())
  [void] $consoleHost.GetType().GetProperty(""IsStandardOutputRedirected"", $bindingFlags).GetValue($consoleHost, @())
  $bindingFlags = [Reflection.BindingFlags] ""Instance,NonPublic,GetField""
  $field = $consoleHost.GetType().GetField(""standardOutputWriter"", $bindingFlags)
  $field.SetValue($consoleHost, [Console]::Out)
  [void] $consoleHost.GetType().GetProperty(""IsStandardErrorRedirected"", $bindingFlags).GetValue($consoleHost, @())
  $field2 = $consoleHost.GetType().GetField(""standardErrorWriter"", $bindingFlags)
  $field2.SetValue($consoleHost, [Console]::Error)
} catch {
  Write-Output ""Unable to apply redirection fix""
}
";
                    pipeline.Commands.Add(new Command(outputRedirectionFixScript, isScript: true, useLocalScope: false));

                    if (additionalActionsBeforeScript != null)
                    {
                        additionalActionsBeforeScript.Invoke(pipeline);
                    }

                    pipeline.Commands.Add(new Command(commandToRun, isScript: true, useLocalScope: false));

                    try
                    {
                        pipeline.Invoke();
                    }
                    catch (RuntimeException ex)
                    {
                        var errorStackTrace = ex.StackTrace;
                        var record          = ex.ErrorRecord;
                        if (record != null)
                        {
                            // not available in v1
                            //errorStackTrace = record.ScriptStackTrace;
                            var scriptStackTrace = record.GetType().GetProperty("ScriptStackTrace");
                            if (scriptStackTrace != null)
                            {
                                var scriptError = scriptStackTrace.GetValue(record, null).to_string();
                                if (!string.IsNullOrWhiteSpace(scriptError))
                                {
                                    errorStackTrace = scriptError;
                                }
                            }
                        }
                        this.Log().Error("ERROR: {0}{1}".format_with(ex.Message.escape_curly_braces(), !config.Debug ? string.Empty : "{0} {1}".format_with(Environment.NewLine, errorStackTrace.escape_curly_braces())));
                    }
                    catch (Exception ex)
                    {
                        // Unfortunately this doesn't print line number and character. It might be nice to get back to those items unless it involves tons of work.
                        this.Log().Error("ERROR: {0}{1}".format_with(ex.Message.escape_curly_braces(), !config.Debug ? string.Empty : "{0} {1}".format_with(Environment.NewLine, ex.StackTrace.escape_curly_braces())));
                    }

                    if (pipeline.PipelineStateInfo != null)
                    {
                        switch (pipeline.PipelineStateInfo.State)
                        {
                        // disconnected is not available unless the assembly version is at least v3
                        //case PipelineState.Disconnected:
                        case PipelineState.Running:
                        case PipelineState.NotStarted:
                        case PipelineState.Failed:
                        case PipelineState.Stopping:
                        case PipelineState.Stopped:
                            if (host.ExitCode == 0)
                            {
                                host.SetShouldExit(1);
                            }
                            host.HostException = pipeline.PipelineStateInfo.Reason;
                            break;

                        case PipelineState.Completed:
                            if (host.ExitCode == -1)
                            {
                                host.SetShouldExit(0);
                            }
                            break;
                        }
                    }
                }
            }

            this.Log().Debug("Built-in PowerShell host called with ['{0}'] exited with '{1}'.".format_with(commandToRun.escape_curly_braces(), host.ExitCode));

            result.ExitCode             = host.ExitCode;
            result.StandardErrorWritten = host.StandardErrorWritten;

            return(result);
        }
Exemple #2
0
        private PowerShellExecutionResults run_host(ChocolateyConfiguration config, string chocoPowerShellScript)
        {
            var result = new PowerShellExecutionResults();
            string commandToRun = wrap_script_with_module(chocoPowerShellScript, config);
            var host = new PoshHost(config);
            this.Log().Debug(() => "Calling built-in PowerShell host with ['{0}']".format_with(commandToRun.escape_curly_braces()));

            var initialSessionState = InitialSessionState.CreateDefault();
            // override system execution policy without accidentally setting it
            initialSessionState.AuthorizationManager = new AuthorizationManager("choco");
            using (var runspace = RunspaceFactory.CreateRunspace(host, initialSessionState))
            {
                runspace.Open();

                // this will affect actual execution policy
                //RunspaceInvoke invoker = new RunspaceInvoke(runspace);
                //invoker.Invoke("Set-ExecutionPolicy ByPass");

                using (var pipeline = runspace.CreatePipeline())
                {
                    // The powershell host itself handles the following items:
                    // * Write-Debug
                    // * Write-Host
                    // * Write-Verbose
                    // * Write-Warning
                    //
                    // the two methods below will pick up Write-Output and Write-Error

                    // Write-Output
                    pipeline.Output.DataReady += (sender, args) =>
                    {
                        PipelineReader<PSObject> reader = sender as PipelineReader<PSObject>;

                        if (reader != null)
                        {
                            while (reader.Count > 0)
                            {
                                host.UI.WriteLine(reader.Read().to_string());
                            }
                        }
                    };

                    // Write-Error
                    pipeline.Error.DataReady += (sender, args) =>
                    {
                        PipelineReader<object> reader = sender as PipelineReader<object>;

                        if (reader != null)
                        {
                            while (reader.Count > 0)
                            {
                                host.UI.WriteErrorLine(reader.Read().to_string());
                            }
                        }
                    };

                    pipeline.Commands.Add(new Command(commandToRun, isScript: true, useLocalScope: false));

                    try
                    {
                        pipeline.Invoke();
                    }
                    catch (RuntimeException ex)
                    {
                        var errorStackTrace = ex.StackTrace;
                        var record = ex.ErrorRecord;
                        if (record != null)
                        {
                            // not available in v1
                            //errorStackTrace = record.ScriptStackTrace;
                            var scriptStackTrace = record.GetType().GetProperty("ScriptStackTrace");
                            if (scriptStackTrace != null)
                            {
                                var scriptError = scriptStackTrace.GetValue(record, null).to_string();
                                if (!string.IsNullOrWhiteSpace(scriptError)) errorStackTrace = scriptError;
                            }
                        }
                        this.Log().Error("ERROR: {0}{1}".format_with(ex.Message, !config.Debug ? string.Empty : "{0} {1}".format_with(Environment.NewLine,errorStackTrace)));
                    }
                    catch (Exception ex)
                    {
                        // Unfortunately this doesn't print line number and character. It might be nice to get back to those items unless it involves tons of work.
                        this.Log().Error("ERROR: {0}{1}".format_with(ex.Message, !config.Debug ? string.Empty : "{0} {1}".format_with(Environment.NewLine,ex.StackTrace)));
                    }

                    if (pipeline.PipelineStateInfo != null)
                    {
                        switch (pipeline.PipelineStateInfo.State)
                        {
                            // disconnected is not available unless the assembly version is at least v3
                            //case PipelineState.Disconnected:
                            case PipelineState.Running:
                            case PipelineState.NotStarted:
                            case PipelineState.Failed:
                            case PipelineState.Stopping:
                            case PipelineState.Stopped:
                                host.SetShouldExit(1);
                                host.HostException = pipeline.PipelineStateInfo.Reason;
                                break;
                            case PipelineState.Completed:
                                host.SetShouldExit(0);
                                break;
                        }

                    }
                }
            }

            this.Log().Debug("Built-in PowerShell host called with ['{0}'] exited with '{1}'.".format_with(commandToRun.escape_curly_braces(), host.ExitCode));

            result.ExitCode = host.ExitCode;
            result.StandardErrorWritten = host.StandardErrorWritten;

            return result;
        }
Exemple #3
0
        public PowerShellExecutionResults run_host(ChocolateyConfiguration config, string chocoPowerShellScript, Action<Pipeline> additionalActionsBeforeScript)
        {
            // since we control output in the host, always set these true
            Environment.SetEnvironmentVariable("ChocolateyEnvironmentDebug", "true");
            Environment.SetEnvironmentVariable("ChocolateyEnvironmentVerbose", "true");

            var result = new PowerShellExecutionResults();
            string commandToRun = wrap_script_with_module(chocoPowerShellScript, config);
            var host = new PoshHost(config);
            this.Log().Debug(() => "Calling built-in PowerShell host with ['{0}']".format_with(commandToRun.escape_curly_braces()));

            var initialSessionState = InitialSessionState.CreateDefault();
            // override system execution policy without accidentally setting it
            initialSessionState.AuthorizationManager = new AuthorizationManager("choco");
            using (var runspace = RunspaceFactory.CreateRunspace(host, initialSessionState))
            {
                runspace.Open();

                // this will affect actual execution policy
                //RunspaceInvoke invoker = new RunspaceInvoke(runspace);
                //invoker.Invoke("Set-ExecutionPolicy ByPass");

                using (var pipeline = runspace.CreatePipeline())
                {
                    // The powershell host itself handles the following items:
                    // * Write-Debug
                    // * Write-Host
                    // * Write-Verbose
                    // * Write-Warning
                    //
                    // the two methods below will pick up Write-Output and Write-Error

                    // Write-Output
                    pipeline.Output.DataReady += (sender, args) =>
                    {
                        PipelineReader<PSObject> reader = sender as PipelineReader<PSObject>;

                        if (reader != null)
                        {
                            while (reader.Count > 0)
                            {
                                host.UI.WriteLine(reader.Read().to_string().escape_curly_braces());
                            }
                        }
                    };

                    // Write-Error
                    pipeline.Error.DataReady += (sender, args) =>
                    {
                        PipelineReader<object> reader = sender as PipelineReader<object>;

                        if (reader != null)
                        {
                            while (reader.Count > 0)
                            {
                                host.UI.WriteErrorLine(reader.Read().to_string().escape_curly_braces());
                            }
                        }
                    };

                    var documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments, Environment.SpecialFolderOption.DoNotVerify);
                    var currentUserCurrentHostProfile = _fileSystem.combine_paths(documentsFolder, "WindowsPowerShell\\Microsoft.PowerShell_profile.ps1");
                    var recreateProfileScript = @"
            if ((Test-Path(""{0}"")) -and ($profile -eq $null -or $profile -eq '')) {{
              $global:profile = ""{1}""
            }}
            ".format_with(documentsFolder, currentUserCurrentHostProfile);

                    pipeline.Commands.Add(new Command(recreateProfileScript, isScript: true, useLocalScope: false));

                    // The PowerShell Output Redirection bug affects System.Management.Automation
                    // it appears with v3 more than others. It is already known to affect v2
                    // this implements the redirection fix from the post below, fixed up with some comments
                    // http://www.leeholmes.com/blog/2008/07/30/workaround-the-os-handles-position-is-not-what-filestream-expected/
                    const string outputRedirectionFixScript = @"
            try {
              $bindingFlags = [Reflection.BindingFlags] ""Instance,NonPublic,GetField""
              $objectRef = $host.GetType().GetField(""externalHostRef"", $bindingFlags).GetValue($host)
              $bindingFlags = [Reflection.BindingFlags] ""Instance,NonPublic,GetProperty""
              $consoleHost = $objectRef.GetType().GetProperty(""Value"", $bindingFlags).GetValue($objectRef, @())
              [void] $consoleHost.GetType().GetProperty(""IsStandardOutputRedirected"", $bindingFlags).GetValue($consoleHost, @())
              $bindingFlags = [Reflection.BindingFlags] ""Instance,NonPublic,GetField""
              $field = $consoleHost.GetType().GetField(""standardOutputWriter"", $bindingFlags)
              $field.SetValue($consoleHost, [Console]::Out)
              [void] $consoleHost.GetType().GetProperty(""IsStandardErrorRedirected"", $bindingFlags).GetValue($consoleHost, @())
              $field2 = $consoleHost.GetType().GetField(""standardErrorWriter"", $bindingFlags)
              $field2.SetValue($consoleHost, [Console]::Error)
            } catch {
              Write-Output ""Unable to apply redirection fix""
            }
            ";
                    pipeline.Commands.Add(new Command(outputRedirectionFixScript, isScript: true, useLocalScope: false));

                    if (additionalActionsBeforeScript != null) additionalActionsBeforeScript.Invoke(pipeline);

                    pipeline.Commands.Add(new Command(commandToRun, isScript: true, useLocalScope: false));

                    try
                    {
                        pipeline.Invoke();
                    }
                    catch (RuntimeException ex)
                    {
                        var errorStackTrace = ex.StackTrace;
                        var record = ex.ErrorRecord;
                        if (record != null)
                        {
                            // not available in v1
                            //errorStackTrace = record.ScriptStackTrace;
                            var scriptStackTrace = record.GetType().GetProperty("ScriptStackTrace");
                            if (scriptStackTrace != null)
                            {
                                var scriptError = scriptStackTrace.GetValue(record, null).to_string();
                                if (!string.IsNullOrWhiteSpace(scriptError)) errorStackTrace = scriptError;
                            }
                        }
                        this.Log().Error("ERROR: {0}{1}".format_with(ex.Message.escape_curly_braces(), !config.Debug ? string.Empty : "{0} {1}".format_with(Environment.NewLine, errorStackTrace.escape_curly_braces())));
                    }
                    catch (Exception ex)
                    {
                        // Unfortunately this doesn't print line number and character. It might be nice to get back to those items unless it involves tons of work.
                        this.Log().Error("ERROR: {0}{1}".format_with(ex.Message.escape_curly_braces(), !config.Debug ? string.Empty : "{0} {1}".format_with(Environment.NewLine, ex.StackTrace.escape_curly_braces())));
                    }

                    if (pipeline.PipelineStateInfo != null)
                    {
                        switch (pipeline.PipelineStateInfo.State)
                        {
                            // disconnected is not available unless the assembly version is at least v3
                            //case PipelineState.Disconnected:
                            case PipelineState.Running:
                            case PipelineState.NotStarted:
                            case PipelineState.Failed:
                            case PipelineState.Stopping:
                            case PipelineState.Stopped:
                                if (host.ExitCode == 0) host.SetShouldExit(1);
                                host.HostException = pipeline.PipelineStateInfo.Reason;
                                break;
                            case PipelineState.Completed:
                                if (host.ExitCode == -1) host.SetShouldExit(0);
                                break;
                        }

                    }
                }
            }

            this.Log().Debug("Built-in PowerShell host called with ['{0}'] exited with '{1}'.".format_with(commandToRun.escape_curly_braces(), host.ExitCode));

            result.ExitCode = host.ExitCode;
            result.StandardErrorWritten = host.StandardErrorWritten;

            return result;
        }
        private PowerShellExecutionResults run_host(ChocolateyConfiguration config, string chocoPowerShellScript)
        {
            var    result       = new PowerShellExecutionResults();
            string commandToRun = wrap_script_with_module(chocoPowerShellScript, config);
            var    host         = new PoshHost(config);

            this.Log().Debug(() => "Calling built-in PowerShell host with ['{0}']".format_with(commandToRun.escape_curly_braces()));

            var initialSessionState = InitialSessionState.CreateDefault();

            // override system execution policy without accidentally setting it
            initialSessionState.AuthorizationManager = new AuthorizationManager("choco");
            using (var runspace = RunspaceFactory.CreateRunspace(host, initialSessionState))
            {
                runspace.Open();

                // this will affect actual execution policy
                //RunspaceInvoke invoker = new RunspaceInvoke(runspace);
                //invoker.Invoke("Set-ExecutionPolicy ByPass");

                using (var pipeline = runspace.CreatePipeline())
                {
                    // The powershell host itself handles the following items:
                    // * Write-Debug
                    // * Write-Host
                    // * Write-Verbose
                    // * Write-Warning
                    //
                    // the two methods below will pick up Write-Output and Write-Error

                    // Write-Output
                    pipeline.Output.DataReady += (sender, args) =>
                    {
                        PipelineReader <PSObject> reader = sender as PipelineReader <PSObject>;

                        if (reader != null)
                        {
                            while (reader.Count > 0)
                            {
                                host.UI.WriteLine(reader.Read().to_string());
                            }
                        }
                    };

                    // Write-Error
                    pipeline.Error.DataReady += (sender, args) =>
                    {
                        PipelineReader <object> reader = sender as PipelineReader <object>;

                        if (reader != null)
                        {
                            while (reader.Count > 0)
                            {
                                host.UI.WriteErrorLine(reader.Read().to_string());
                            }
                        }
                    };

                    pipeline.Commands.Add(new Command(commandToRun, isScript: true, useLocalScope: false));

                    try
                    {
                        pipeline.Invoke();
                    }
                    catch (Exception ex)
                    {
                        // Unfortunately this doesn't print line number and character. It might be nice to get back to those items unless it involves tons of work.
                        this.Log().Error("ERROR: {0}".format_with(ex.Message)); //, !config.Debug ? string.Empty : "{0} {1}".format_with(Environment.NewLine,ex.StackTrace)));
                    }

                    if (pipeline.PipelineStateInfo != null)
                    {
                        switch (pipeline.PipelineStateInfo.State)
                        {
                        // disconnected is not available unless the assembly version is at least v3
                        //case PipelineState.Disconnected:
                        case PipelineState.Running:
                        case PipelineState.NotStarted:
                        case PipelineState.Failed:
                        case PipelineState.Stopping:
                        case PipelineState.Stopped:
                            host.SetShouldExit(1);
                            host.HostException = pipeline.PipelineStateInfo.Reason;
                            break;

                        case PipelineState.Completed:
                            host.SetShouldExit(0);
                            break;
                        }
                    }
                }
            }

            this.Log().Debug("Built-in PowerShell host called with ['{0}'] exited with '{1}'.".format_with(commandToRun.escape_curly_braces(), host.ExitCode));

            result.ExitCode             = host.ExitCode;
            result.StandardErrorWritten = host.StandardErrorWritten;

            return(result);
        }