优秀的编程知识分享平台

网站首页 > 技术文章 正文

C#调用PowerShell,执行多个耗时的命令,并实时输出内容的例子

nanyue 2024-10-25 13:19:44 技术文章 2 ℃

在C#中,你可以使用System.Management.Automation命名空间来调用PowerShell脚本。为了实时输出PowerShell命令执行过程中的内容,你需要将PowerShell命令的输出流(如标准输出流、错误流等)重定向到一个PowerShell对象的相应属性上,并在C#代码中读取这些属性。

下面是一个示例代码,它演示了如何使用C#调用PowerShell,执行多个耗时的命令,并实时输出过程中输出的内容:

csharpusing System;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Threading;

class Program
{
    static void Main()
    {
        // 创建PowerShell实例
        using (PowerShell powerShell = PowerShell.Create())
        {
            // 添加第一个耗时的PowerShell命令
            powerShell.AddScript("Write-Output '开始执行第一个命令...'; Start-Sleep -Seconds 5; Write-Output '第一个命令执行完成。'");

            // 添加第二个耗时的PowerShell命令
            powerShell.AddScript("Write-Output '开始执行第二个命令...'; Start-Sleep -Seconds 3; Write-Output '第二个命令执行完成。'");

            // 将PowerShell对象的输出流和错误流重定向到Collection<PSObject>对象上
            var outputCollection = new Collection<PSObject>();
            var errorCollection = new Collection<ErrorRecord>();
            powerShell.Streams.Output.DataAdded += (sender, e) => outputCollection.Add(powerShell.Streams.Output.ReadToEnd());
            powerShell.Streams.Error.DataAdded += (sender, e) => errorCollection.Add(powerShell.Streams.Error.ReadToEnd());

            // 开始异步执行PowerShell命令
            IAsyncResult asyncResult = powerShell.BeginInvoke();

            // 轮询直到命令执行完成
            while (!asyncResult.IsCompleted)
            {
                // 实时输出输出流中的内容
                foreach (var output in outputCollection)
                {
                    Console.WriteLine(output.ToString());
                }

                // 实时输出错误流中的内容
                foreach (var error in errorCollection)
                {
                    Console.Error.WriteLine(error.Exception.Message);
                }

                // 等待一段时间再次检查,避免忙等
                Thread.Sleep(100);
            }

            // 等待PowerShell命令完全执行完毕
            powerShell.EndInvoke(asyncResult);

            // 清理输出和错误集合
            outputCollection.Clear();
            errorCollection.Clear();
        }

        Console.WriteLine("所有命令执行完毕。");
    }
}

在这个示例中,我们创建了一个PowerShell实例,并添加了两个耗时的PowerShell命令。然后,我们将PowerShell的输出流和错误流重定向到Collection<PSObject>和Collection<ErrorRecord>对象上,并注册了事件处理程序来在数据添加到这些集合时接收通知。

我们使用BeginInvoke方法开始异步执行PowerShell命令,并在一个循环中轮询输出流和错误流的内容,实时输出到控制台。最后,我们使用EndInvoke方法等待所有命令执行完毕,并清理输出和错误集合。

请注意,这个示例使用了Thread.Sleep方法来在轮询之间添加延迟,以避免过度消耗CPU资源。在实际应用中,你可能需要根据具体情况调整这个延迟时间。

此外,请确保你的项目引用了System.Management.Automation程序集,这通常可以通过添加对Microsoft.PowerShell.SDK的NuGet包引用来实现。

System.Management.Automation是.NET程序集,主要用于PowerShell的脚本执行1

System.Management.Automation是PowerShell.exe的解释器,可以在C程序中与这个对象进行交互并执行.ps1脚本1。任何后续调用System.Management.Automation.Cmdlet.WriteObject、System.Management.Automation.Cmdlet.WriteError或多个其他
API的尝试,都会导致这些调用引发System.Management.Automation.Pipelinestoppedexception异常2

Tags:

最近发表
标签列表