5

我正在尝试使用 C# 在运行空间中执行带有参数的 Powershell 文件。不幸的是,我得到以下输出:

提示用户的命令失败,因为主机程序或命令类型不支持用户交互。尝试支持用户交互的主机程序,例如 Windows PowerShell 控制台或 Windows PowerShell ISE,并从不支持用户交互的命令类型(例如 Windows PowerShell 工作流)中删除与提示相关的命令。

我能做什么?

当前的 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;
4

3 回答 3

8

使用Write-Output代替Write-Host

于 2016-08-11T19:39:09.123 回答
5

如果您需要运行使用非关键 cmdlet(如 write-host)的脚本,需要存在完整的 pshost,您可以将“假”函数添加到运行空间,这些函数要么不执行任何操作,要么记录到文本文件(或你想要的任何其他东西。)在这里查看我的其他答案:

如何在其中包含 Write-Host 命令的代码创建的 powershell shell 中执行脚本?

于 2014-09-22T06:58:25.577 回答
1

通过覆盖这两个 cmdlet,我自己为 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 的评论者,这不是许多用例的解决方案。例如,您可能不希望您的用户通知进入您的输出流。

如果您需要使用原始 cmdlet,请使用以下命令:

Microsoft.PowerShell.Utility\Read-Host -Prompt "Enter your input"
于 2016-08-23T13:23:19.757 回答