1

I have a C# function to run a remote Powershell script. I can see that the script is running and all is working well on the remote server, but I can't get any real time output from Powershell.
The ps1 script runs for a long time and has many outputs. The script is running rar.exe, so the output is supposed to be from rar.exe.

Here is the C# function:

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);
    }

The hubs.Clients.All.SendPowerShellResults function is a websocket and it is working - so I can receive data but it's not data from the Powershell output.

I would like to know what is going on here.

4
  • comment retracted Commented Sep 15, 2016 at 21:48
  • The problem might be in D:\backup\test.ps1 Commented Sep 15, 2016 at 21:55
  • what i need to use write-host ? write-output ? in my ps1 script to see outputs ? Commented Sep 18, 2016 at 9:17
  • Can you expand your post to include what's in test1.ps1? Commented Sep 20, 2016 at 3:11

2 Answers 2

1

Check to see if this topic helps:

Get Powershell command's output when invoked through code

The streams holds a "PsDataCollection" type, each item containing our desired output. This types contains the "DateAdded" event. You can use DateAdded event to output the data as soon it is added!

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

Sign up to request clarification or add additional context in comments.

Comments

0

I had a similar issue, so created the example below to allow retrieving the results in real time using an Async Enumerable to get results from a PowerShell Pipeline.

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; }
        }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.