简体   繁体   English

如何从调用该 PowerShell 脚本的 C# 代码回答 Read-Host?

[英]How to answer to Read-Host from C# code that invoked that PowerShell script?

I need to run PowerShell script from inside my C# code.我需要从我的 C# 代码中运行 PowerShell 脚本。 That is easy.那很容易。 But then, my PowerShell script contains several Read-Host commands.但是,我的 PowerShell 脚本包含几个 Read-Host 命令。 Normally, the script execution would stop and the user should manually enter some value to PowerShell consoleas an answer.通常,脚本执行会停止,用户应该手动向 PowerShell 控制台输入一些值作为答案。 But what I need is to answer to these Read-Host requests from the same code in C# that executed and controls the flow of that script.但我需要的是从执行和控制该脚本流程的 C# 中的相同代码响应这些读取主机请求。 In other words I need my script to stop at some point and await for some data input from my C# code, then get it and continue execution.换句话说,我需要我的脚本在某个时候停止并等待从我的 C# 代码输入一些数据,然后获取它并继续执行。

I found how to run PS from C#, I found how to pass arguments or initial variables from C# to PS script when launching it, but I can't find any way how to make my script await for some data from the host application, receive it and continue exectuion within host application, all these during runtime of script, not on its launch.我找到了如何从 C# 运行 PS,我找到了如何在启动它时将参数或初始变量从 C# 传递到 PS 脚本,但我找不到任何方法如何让我的脚本等待来自主机应用程序的一些数据,接收它并在主机应用程序中继续执行,所有这些都在脚本运行时,而不是在其启动时。

Can you please guide me to some direction fo search or code that might help?你能指导我一些可能有帮助的搜索或代码方向吗?

You can call WriteLine() on the StandardInput of the process.您可以在流程的StandardInput上调用WriteLine() That will provide data for one Read-Host in the script.这将为脚本中的一个Read-Host提供数据。

To do so make sure UseShellExecute of the respective ProcessStartInfo is set to false and its RedirectStandardInput to true .为此,请确保将相应ProcessStartInfo UseShellExecute设置为false并将其RedirectStandardInputtrue

So for example所以例如

    Process p = Process.Start(new ProcessStartInfo()
    {
        FileName = "powershell",
        Arguments = @"C:\Users\Konstantin\ps.ps1",
        UseShellExecute = false,
        RedirectStandardInput = true,
    });

    p.StandardInput.WriteLine("abc");

will provide "abc" to the first Read-Host of the script C:\\Users\\Konstantin\\ps.ps1 .将为脚本C:\\Users\\Konstantin\\ps.ps1的第一个Read-Host提供“abc”。

If there are more Read-Host s call WriteLine() again.如果有更多Read-Host再次调用WriteLine() Or you can use string concatenation with StandardInput.NewLine and just use Write .或者,您可以将字符串连接与StandardInput.NewLine一起使用,然后只使用Write For example例如

p.StandardInput.Write("abc" + StandardInput.NewLine + "xyz" + StandardInput.NewLine);

will provide "abc" for the first and "xyz" for the second Read-Host .将为第一个提供“abc”,为第二个Read-Host提供“xyz”。

If you're invoking the PowerShell script in-process then the only way to override the behavior of Read-Host is to define a custom PSHost for the process.如果您在进程内调用 PowerShell 脚本,则覆盖Read-Host行为的唯一方法是为该进程定义自定义PSHost The behavior is defined by the method PSHostUserInterface.ReadLine .该行为由方法PSHostUserInterface.ReadLine定义。 Here is a bare minimum example of what you need to override just Read-Host .这是您只需要覆盖Read-Host最低限度示例。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Runspaces;
using System.Security;


namespace CustomHostExample
{
    public static class Program
    {
        public static void Main()
        {
            var host = new CustomPSHost();
            using (Runspace rs = RunspaceFactory.CreateRunspace(host))
            using (PowerShell pwsh = PowerShell.Create())
            {
                rs.Open();
                pwsh.Runspace = rs;
                pwsh.AddCommand("Read-Host").Invoke();
            }
        }
    }

    public class CustomPSHost : PSHost
    {
        public override string Name => "Custom Host";

        public override Version Version => new Version(1, 0, 0, 0);

        public override Guid InstanceId { get; } = Guid.NewGuid();

        public override PSHostUserInterface UI { get; } = new CustomPSHostUserInterface();

        public override CultureInfo CurrentCulture => CultureInfo.CurrentCulture;

        public override CultureInfo CurrentUICulture => CultureInfo.CurrentUICulture;

        public override void EnterNestedPrompt()
            => throw new NotImplementedException();

        public override void ExitNestedPrompt()
            => throw new NotImplementedException();

        public override void NotifyBeginApplication()
            => throw new NotImplementedException();

        public override void NotifyEndApplication()
            => throw new NotImplementedException();

        public override void SetShouldExit(int exitCode)
            => throw new NotImplementedException();
    }

    public class CustomPSHostUserInterface : PSHostUserInterface
    {
        public override PSHostRawUserInterface RawUI { get; } = new CustomPSHostRawUserInterface();

        public override string ReadLine()
        {
            return Console.ReadLine();
        }

        public override Dictionary<string, PSObject> Prompt(
            string caption,
            string message,
            Collection<FieldDescription> descriptions)
            => throw new NotImplementedException();

        public override int PromptForChoice(
            string caption,
            string message,
            Collection<ChoiceDescription> choices,
            int defaultChoice)
            => throw new NotImplementedException();

        public override PSCredential PromptForCredential(
            string caption,
            string message,
            string userName,
            string targetName,
            PSCredentialTypes allowedCredentialTypes,
            PSCredentialUIOptions options)
            => throw new NotImplementedException();

        public override PSCredential PromptForCredential(
            string caption,
            string message,
            string userName,
            string targetName)
            => throw new NotImplementedException();

        public override SecureString ReadLineAsSecureString()
            => throw new NotImplementedException();

        public override void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value)
            => throw new NotImplementedException();

        public override void Write(string value)
            => throw new NotImplementedException();

        public override void WriteDebugLine(string message)
            => throw new NotImplementedException();

        public override void WriteErrorLine(string value)
            => throw new NotImplementedException();

        public override void WriteLine(string value)
            => throw new NotImplementedException();

        public override void WriteProgress(long sourceId, ProgressRecord record)
            => throw new NotImplementedException();

        public override void WriteVerboseLine(string message)
            => throw new NotImplementedException();

        public override void WriteWarningLine(string message)
            => throw new NotImplementedException();
    }

    public class CustomPSHostRawUserInterface : PSHostRawUserInterface
    {
        public override ConsoleColor BackgroundColor
        {
            get => throw new NotImplementedException();
            set => throw new NotImplementedException();
        }

        public override Size BufferSize
        {
            get => throw new NotImplementedException();
            set => throw new NotImplementedException();
        }

        public override Coordinates CursorPosition
        {
            get => throw new NotImplementedException();
            set => throw new NotImplementedException();
        }

        public override int CursorSize
        {
            get => throw new NotImplementedException();
            set => throw new NotImplementedException();
        }

        public override ConsoleColor ForegroundColor
        {
            get => throw new NotImplementedException();
            set => throw new NotImplementedException();
        }

        public override Coordinates WindowPosition
        {
            get => throw new NotImplementedException();
            set => throw new NotImplementedException();
        }

        public override Size WindowSize
        {
            get => throw new NotImplementedException();
            set => throw new NotImplementedException();
        }

        public override string WindowTitle
        {
            get => throw new NotImplementedException();
            set => throw new NotImplementedException();
        }

        public override bool KeyAvailable
            => throw new NotImplementedException();

        public override Size MaxPhysicalWindowSize
            => throw new NotImplementedException();

        public override Size MaxWindowSize
            => throw new NotImplementedException();

        public override void FlushInputBuffer()
            => throw new NotImplementedException();

        public override BufferCell[,] GetBufferContents(Rectangle rectangle)
            => throw new NotImplementedException();

        public override KeyInfo ReadKey(ReadKeyOptions options)
            => throw new NotImplementedException();

        public override void ScrollBufferContents(
            Rectangle source,
            Coordinates destination,
            Rectangle clip,
            BufferCell fill)
            => throw new NotImplementedException();

        public override void SetBufferContents(Coordinates origin, BufferCell[,] contents)
            => throw new NotImplementedException();

        public override void SetBufferContents(Rectangle rectangle, BufferCell fill)
            => throw new NotImplementedException();
    }
}

Note: Every method shown that doesn't throw a NotImplementedException must be implemented or PowerShell will deadlock or throw.注意:所示的每个不抛出NotImplementedException必须实现,否则 PowerShell 将死锁或抛出。 More methods will need to be implemented depending on what else of PSHost is called.根据调用PSHost其他内容,需要实现更多方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM