PowerShell 脚本未在控制台上显示任何输出

问题描述 投票:0回答:3

我有以下代码片段,它从后端的 C# 文件运行。

using (Process process = new Process())
{
    process.StartInfo.FileName = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
    String cmd = "C:\\Users\\xyz\\AppData\\Local\\Temp\\2\\Demo.ps1";
    process.StartInfo.Arguments = cmd;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = false;
    process.StartInfo.RedirectStandardError = true;
    StringBuilder error = new StringBuilder();

    process.Start();

    while (true)
    {
        bool hasExited = process.HasExited;

        String errorStr = null;
        while ((errorStr = process.StandardError.ReadLine()) != null)
            error.AppendLine(errorStr);

        if (hasExited)
            break;

        Thread.Sleep(100);
    }

    if (process.ExitCode != 0 || error.Length > 0)
        throw new Exception(error.ToString());
}

演示.ps1

write-host "Working Properly now! "

我希望在同一个打开的 PowerShell 窗口中打印该字符串,但不知何故,它没有向打开的 PowerShell 窗口显示任何输出。如果我将输出重定向到文本文件,那么它就清晰可见。

c# powershell scripting
3个回答
1
投票

问题是由于代码中 Process 类的设置方式造成的。具体来说,属性 UseShellExecute、RedirectStandardOutput 和 RedirectStandardError。

当您将 RedirectStandardOutput 或 RedirectStandardError 设置为 true 时,这意味着 C# 程序将分别捕获来自进程的输出或错误流。在您的例子中,您已将 RedirectStandardError 设置为 true,因此 C# 程序正在捕获错误流,但您已将 RedirectStandardOutput 设置为 false,这意味着未捕获输出流。

将 UseShellExecute 设置为 true。 将 RedirectStandardOutput 和 RedirectStandardError 设置为 false。 删除从 StandardError 读取的代码以及检查进程退出的循环。 这是修改后的代码:

要在 PowerShell 窗口中查看输出,您可以进行以下更改:

using (Process process = new Process())
{
process.StartInfo.FileName = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
String cmd = "-NoExit C:\\Users\\xyz\\AppData\\Local\\Temp\\2\\Demo.ps1"; // Added -NoExit to keep the PowerShell window open
process.StartInfo.Arguments = cmd;
process.StartInfo.UseShellExecute = true; // Changed to true
process.StartInfo.RedirectStandardOutput = false; // Remains the same
process.StartInfo.RedirectStandardError = false; // Changed to false

process.Start();
process.WaitForExit(); // Wait for the process to exit

}

cmd 中的 -NoExit 参数可确保 PowerShell 窗口在脚本完成后保持打开状态,以便您查看输出。如果删除它,窗口将在脚本执行后立即关闭。

此修改后的代码现在将打开一个新的 PowerShell 窗口并运行 Demo.ps1 脚本,在该窗口中显示输出。


0
投票

C# 中直接有一个功能。它简化了交互,也更容易调试。

try
{
    ScriptBuilder script = new ScriptBuilder();
    script.LoadScript(File.ReadAllText(@"some.ps1"));
    script.AddParameters(new Dictionary<string, string>
    {
        {"param1", "param1" }
    });
    script.Run();
    System.Console.WriteLine("Hit any key to exit.");
    System.Console.ReadKey();
}
catch (Exception ex)
{
    System.Console.WriteLine(ex.Message);
}

这是一个简单的包装器

public class ScriptBuilder
{
    private readonly PowerShell powerShellScript;

    public ScriptBuilder()
    {
        powerShellScript = PowerShell.Create();
    }

    public void LoadScript(string script)
    {
        powerShellScript.AddScript(script);
    }

    public void AddParameters(Dictionary<string, string> parameters)
    {
        foreach (var parameter in parameters)
        {
            powerShellScript.AddParameter(parameter.Key, parameter.Value);
        }
    }

    public void Run()
    {
        var output = new PSDataCollection<PSObject>();
        output.DataAdded += Output_DataAdded;

        powerShellScript
            .BeginInvoke<PSObject, PSObject>(null, output)
            .AsyncWaitHandle
            .WaitOne();

        powerShellScript.Invoke();
    }

    private static void Output_DataAdded(object? sender, DataAddedEventArgs e)
    {
        if (sender == null)
        {
            return;
        }
        PSObject newRecord = ((PSDataCollection<PSObject>)sender)[e.Index];
        Console.WriteLine(newRecord);
    }
}

此示例将参数传递给脚本并执行脚本。

这些是一些可以帮助进一步扩展代码的链接:

powershell-主机

系统.管理.自动化.powershell

PowerShell 输出


-1
投票

您观察到的行为是因为您将 PowerShell 作为具有不同输入和输出流的单独进程运行,并且 PowerShell 脚本生成的输出不会自动显示在父控制台窗口中。当您以这种方式运行 PowerShell 时,如果您想在父控制台中看到输出,则需要显式处理输出的重定向。

删除这一行 process.StartInfo.RedirectStandardOutput = false;从你的代码。此行告诉进程不要重定向标准输出。

修改 Demo.ps1 脚本以使用 Write-Output cmdlet 而不是 Write-Host。

Write-Output "Working Properly now !"

修改代码

using (Process process = new Process())
{
    process.StartInfo.FileName = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
    String cmd = "C:\\Users\\xyz\\AppData\\Local\\Temp\\2\\Demo.ps1";
    process.StartInfo.Arguments = cmd;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardError = true;
    StringBuilder error = new StringBuilder();

    process.Start();

    while (true)
    {
        bool hasExited = process.HasExited;

        String errorStr = null;
        while ((errorStr = process.StandardError.ReadLine()) != null)
            error.AppendLine(errorStr);

        if (hasExited)
            break;

        Thread.Sleep(100);
    }

    if (process.ExitCode != 0 || error.Length > 0)
        throw new Exception(error.ToString());
}
© www.soinside.com 2019 - 2024. All rights reserved.