#c# #powershell
#c# #powershell
Вопрос:
Мне нужно запустить скрипт PowerShell из моего кода C #. Это просто. Но тогда мой сценарий PowerShell содержит несколько команд Read-Host. Обычно выполнение скрипта останавливается, и пользователь должен вручную ввести некоторое значение в консоль PowerShell в качестве ответа. Но что мне нужно, так это ответить на эти запросы Read-Host из того же кода на C #, который выполняется и управляет потоком этого сценария. Другими словами, мне нужно, чтобы мой скрипт в какой-то момент остановился и ожидал ввода некоторых данных из моего кода C #, затем получил их и продолжил выполнение.
Я нашел, как запустить PS с C #, я нашел, как передать аргументы или начальные переменные с C # скрипту PS при его запуске, но я не могу найти никакого способа, как заставить мой скрипт ожидать некоторых данных от хост-приложения, получать их и продолжать выполнение в хост-приложении, все это во время выполнения скрипта, а не при его запуске.
Не могли бы вы, пожалуйста, указать мне какое-нибудь направление для поиска или код, который мог бы помочь?
Ответ №1:
Вы можете вызвать WriteLine()
от StandardInput
имени процесса. Это предоставит данные для одного из них Read-Host
в сценарии.
Для этого убедитесь, что для UseShellExecute
соответствующего ProcessStartInfo
параметра установлено значение false
, а для его RedirectStandardInput
значения true
.
Так, например
Process p = Process.Start(new ProcessStartInfo()
{
FileName = "powershell",
Arguments = @"C:UsersKonstantinps.ps1",
UseShellExecute = false,
RedirectStandardInput = true,
});
p.StandardInput.WriteLine("abc");
предоставит «abc» для первой Read-Host
части скрипта C:UsersKonstantinps.ps1
.
Если есть еще Read-Host
s, вызовите WriteLine()
еще раз. Или вы можете использовать конкатенацию строк с StandardInput.NewLine
и просто использовать Write
. Например
p.StandardInput.Write("abc" StandardInput.NewLine "xyz" StandardInput.NewLine);
предоставит «abc» для первого и «xyz» для второго Read-Host
.
Ответ №2:
Если вы вызываете сценарий PowerShell в процессе, то единственный способ переопределить поведение Read-Host
— это определить пользовательский PSHost
для процесса. Поведение определяется методом PSHostUserInterface.ReadLine
. Вот минимальный пример того, что вам нужно просто переопределить 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();
}
}
Примечание: Каждый показанный метод, который не выдает a, NotImplementedException
должен быть реализован, иначе PowerShell приведет к взаимоблокировке или выбросит. Потребуется реализовать больше методов в зависимости от того, какой еще из PSHost
вызывается.