【问题标题】:C# Get real time powershell script outputC#获取实时powershell脚本输出
【发布时间】:2017-01-23 03:45:36
【问题描述】:

我有一个 C# 函数来运行远程 Powershell 脚本。 我可以看到脚本正在运行,并且在远程服务器上一切正常,但我无法从 Powershell 获得任何实时输出。
ps1 脚本运行时间长,输出多。该脚本正在运行 rar.exe,因此输出应该来自 rar.exe。

这里是 C# 函数:

public static bool RunBackupPowershell()
    {
        string password = "somepassword";
        string userName = "someuser";
        string shell = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell";
        var target = new Uri("http://someserver:5985/wsman");
        SecureString securepassword = String2SecureString(password);
        PSCredential credential = new PSCredential(userName, securepassword);
        WSManConnectionInfo connectionInfo = new WSManConnectionInfo(target,shell,credential);
        connectionInfo.OpenTimeout = 4 * 60 * 1000;
        connectionInfo.OpenTimeout = 1 * 60 * 1000;
        connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Credssp;

        Runspace remote = RunspaceFactory.CreateRunspace(connectionInfo);

        remote.Open();
        PowerShell PowerShellInstance = PowerShell.Create();
        PowerShellInstance.Runspace = remote;
        PowerShellInstance.AddScript("D:\\backup\\test.ps1");

        PSDataCollection<PSObject> outputCollection = new PSDataCollection<PSObject>();
        outputCollection.DataAdded += outputCollection_DataAdded;
        PowerShellInstance.Streams.Error.DataAdded += Error_DataAdded;
        IAsyncResult result = PowerShellInstance.BeginInvoke<PSObject, PSObject>(null, outputCollection);

        while (result.IsCompleted == false)
        {
            hubs.Clients.All.SendPowerShellResults("Waiting for pipeline to finish...");

            Thread.Sleep(1000);
        }

        hubs.Clients.All.SendPowerShellResults("Execution has stopped. The pipeline state: " + PowerShellInstance.InvocationStateInfo.State);

        foreach (PSObject outputItem in outputCollection)
        {
            hubs.Clients.All.SendPowerShellResults(outputItem);
        }
        return true;

    }

   static void outputCollection_DataAdded(object sender, DataAddedEventArgs e)
    {
        hubs.Clients.All.SendPowerShellResults("Object added to output."+e);
    }
    static void Error_DataAdded(object sender, DataAddedEventArgs e)
    {
        hubs.Clients.All.SendPowerShellResults("An error was written to the Error stream!"+e);
    }

hubs.Clients.All.SendPowerShellResults 函数是一个 websocket,它正在工作 - 所以我可以接收数据,但它不是来自 Powershell 输出的数据。

我想知道这里发生了什么。

【问题讨论】:

  • 评论撤回
  • 问题可能出在D:\backup\test.ps1
  • 我需要使用 write-host 什么?写输出?在我的 ps1 脚本中查看输出?
  • 您能否扩展您的帖子以包含 test1.ps1 中的内容?

标签: c# powershell


【解决方案1】:

查看此主题是否有帮助:

Get Powershell command's output when invoked through code

流包含一个“PsDataCollection”类型,每个项目都包含我们想要的输出。此类型包含“DateAdded”事件。您可以使用 DateAdded 事件在数据添加后立即输出!

https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.psdatacollection-1.dataadded?view=pscore-6.2.0

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,因此创建了下面的示例,以允许使用异步枚举实时检索结果以从 PowerShell 管道获取结果。

    https://gist.github.com/OnKey/83cf98e6adafe5a2b4aaf561b138087b

    static async Task Main(string[] args)
            {
                var script = @"
    For ($i=0; $i -le 5; $i++) {
        $i
        Start-Sleep -s 1 
    }
    ";
                var p = new Program();
                await foreach (var item in p.PowerShellAsyncEnumerable(script))
                {
                    Console.WriteLine(item);
                }
            }
    
            private IAsyncEnumerable<PSObject> PowerShellAsyncEnumerable(string script)
            {
                var rs = RunspaceFactory.CreateRunspace();
                rs.Open();
                var pipeline = rs.CreatePipeline();
                pipeline.Commands.AddScript(script);
    
                return new PsAsyncEnumerable(pipeline);
            }
    
            internal class PsAsyncEnumerable : IAsyncEnumerable<PSObject>
            {
                private readonly Pipeline pipe;
                public PsAsyncEnumerable(Pipeline pipe) => this.pipe = pipe;
    
                public IAsyncEnumerator<PSObject> GetAsyncEnumerator(CancellationToken cancellationToken = new()) 
                    => new PsAsyncEnumerator(this.pipe);
            }
    
            internal class PsAsyncEnumerator : IAsyncEnumerator<PSObject>
            {
                private readonly Pipeline pipe;
                private TaskCompletionSource dataReady = new();
    
                public PsAsyncEnumerator(Pipeline pipe)
                {
                    this.pipe = pipe;
                    this.pipe.Output.DataReady += NotificationHandler;
                    this.pipe.Error.DataReady += NotificationHandler;
                    this.pipe.InvokeAsync();
                }
                
                private void NotificationHandler(object sender, EventArgs e)
                {
                    this.dataReady.SetResult();
                }
                
                public ValueTask DisposeAsync()
                {
                    this.pipe.Dispose();
                    return ValueTask.CompletedTask;
                }
    
                public async ValueTask<bool> MoveNextAsync()
                {
                    while (!this.pipe.Output.EndOfPipeline)
                    {
                        var item = this.pipe.Output.NonBlockingRead(1).FirstOrDefault();
                        if (item != null)
                        {
                            this.Current = item;
                            return true;
                        }
                    
                        await this.dataReady.Task;
                        this.dataReady = new TaskCompletionSource();
                    }
    
                    return false;
                }
    
                public PSObject Current { get; private set; }
            }
    

    【讨论】:

      猜你喜欢
      • 2020-10-09
      • 1970-01-01
      • 2018-06-09
      • 1970-01-01
      • 2021-07-20
      • 1970-01-01
      • 1970-01-01
      • 2011-11-16
      • 1970-01-01
      相关资源
      最近更新 更多