C# Runspace Powershell (интерактивный)
Я пытаюсь с C# выполнить файл Powershell с параметрами в пространстве выполнения. К сожалению, я получаю следующий вывод:
A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
Что я мог сделать?
Текущий код C#. для этого нужно выполнить команды, которые будут в файле PS и вернуть строку json.
public string ExecuteCommandDirect(int psId, string psMaster, string psFile)
{
String FullPsFilePath = @"C:\CloudPS\" + psFile + ".ps1";
String PsParameters = FullPsFilePath + " -psId " + psId + " -psMaster " + psMaster + " -NonInteractive";
// Create Powershell Runspace
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
// Create pipeline and add commands
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(PsParameters);
// Execute Script
Collection<PSObject> results = new Collection<PSObject>();
try
{
results = pipeline.Invoke();
}
catch (Exception ex)
{
results.Add(new PSObject((object)ex.Message));
}
// Close runspace
runspace.Close();
//Script results to string
StringBuilder stringBuilder = new StringBuilder();
foreach (PSObject obj in results)
{
Debug.WriteLine(obj);
stringBuilder.AppendLine(obj.ToString());
}
return stringBuilder.ToString();
}
PS код:
param([int]$psId = 0, [string]$psMaster = 'localhost');
$date = Get-Date -Format 'h:m:s' | ConvertTo-Json;
Write-Host $date;
exit;
3 ответа
Если вам нужно запустить сценарий, который использует некритические командлеты, такие как write-host, для которых требуется наличие полноценного pshost, вы можете добавить "поддельные" функции в пространство выполнения, которые либо ничего не делают, либо регистрируются в текстовом файле (или все, что вы хотите.) Смотрите мой другой ответ здесь:
Я сам решил эту проблему для Read-Host и Write-Host, переопределив эти два командлета. В моем решении я молча отбрасываю все, что отправлено на Write-Host, но мне нужно реализовать Read-Host. Это запускает новый процесс powershell и возвращает результаты.
string readHostOverride = @"
function Read-Host {
param(
[string]$Prompt
)
$StartInfo = New-Object System.Diagnostics.ProcessStartInfo
#$StartInfo.CreateNoWindow = $true
$StartInfo.UseShellExecute = $false
$StartInfo.RedirectStandardOutput = $true
$StartInfo.RedirectStandardError = $true
$StartInfo.FileName = 'powershell.exe'
$StartInfo.Arguments = @(""-Command"", ""Read-Host"", ""-Prompt"", ""'$Prompt'"")
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $StartInfo
[void]$Process.Start()
$Output = $Process.StandardOutput.ReadToEnd()
$Process.WaitForExit()
return $Output.TrimEnd()
}
";
string writeHostOverride = @"
function Write-Host {
}
";
Run(readHostOverride);
Run(writeHostOverride);
Неудивительно, что Run() - мой метод выполнения powershell.
Вы можете легко расширить это для реализации Write-Host; дайте мне знать, если у вас возникнут трудности.
Для комментаторов, предлагающих переключение на Write-Output вместо Write-Host, это НЕ решение для многих случаев использования. Вы, возможно, не хотите, чтобы ваши пользовательские уведомления входили в ваш поток вывода, например.
Если вам нужно использовать оригинальные командлеты, используйте это:
Microsoft.PowerShell.Utility\Read-Host -Prompt "Enter your input"