Get Powershell command's output when invoked through code

33,170

Unless you're targeting PowerShell 1.0, there's no need to set up your runspace and pipeline manually, create an instance of the PowerShell class instead:

PowerShell psinstance = PowerShell.Create();
psinstance.AddScript(scriptPath);
var results = psinstance.Invoke();

Way simpler.


Now, the PowerShell class exposes the various non-standard output streams (Verbose, Debug, Error etc.) - including the Progress Stream - via the Streams property so you can subscribe to it, like so:

psinstance.Streams.Progress.DataAdded += myProgressEventHandler;

And then in your event handler:

static void myProgressEventHandler(object sender, DataAddedEventArgs e)
{
    ProgressRecord newRecord = ((PSDataCollection<ProgressRecord>)sender)[e.Index];
    if (newRecord.PercentComplete != -1)
    {
        Console.Clear();
        Console.WriteLine("Progress updated: {0}", newRecord.PercentComplete);
    }
}

As an example, here is that event handler shown above in action, while running a sample script that writes progress information (sample script posted below) in a simple console application:

readProgress

Test-Progress.ps1

function Test-Progress
{
    param()

    Write-Progress -Activity 'Testing progress' -Status 'Starting' -PercentComplete 0
    Start-Sleep -Milliseconds 600
    1..10 |ForEach-Object{
        Write-Progress -Activity "Testing progress" -Status 'Progressing' -PercentComplete $(5 + 6.87 * $_)
        Start-Sleep -Milliseconds 400
    }
    Write-Progress -Activity 'Testing progress' -Status 'Ending' -PercentComplete 99
    Start-Sleep -Seconds 2
    Write-Progress -Activity 'Testing progress' -Status 'Done' -Completed
}

Test-Progress
Share:
33,170
Muhammad Murad Haider
Author by

Muhammad Murad Haider

Updated on December 22, 2020

Comments

  • Muhammad Murad Haider
    Muhammad Murad Haider over 3 years

    I have written a piece of code (in C#) to execute a Powershell script (specifically Azure PowerShell) using System.Management.Automation. The powershell script basically uploads a vhd in a container on Azure, which shows the upload progress and time elapsed etc when command is manually entered through azure Powershell. Through code everything works fine but i want to get the result/output of a command (i.e. upload progress, time elapsed), during command execution (i.e. pipeline.invoke();) here is the code:

     RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
     Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
     runspace.Open();
     RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
     Pipeline pipeline = runspace.CreatePipeline();
    
     Command myCommand = new Command(scriptPath);
     foreach (var argument in arguments)
     {
         myCommand.Parameters.Add(new CommandParameter(argument.Key, argument.Value));
     }
     pipeline.Commands.Add(myCommand);
    
     var results = pipeline.Invoke(); // i want to get results here (i.e. during command execution) 
     foreach (var psObject in results)
     {
         System.Diagnostics.Debug.Write(psObject.BaseObject.ToString());
     }
    

    Please guide if it is possible to retrieve live output from Powershell.

  • Ionut Enache
    Ionut Enache over 5 years
    Hi, I am using the PowerShell class but the DataAdded event is never triggered for me. My question is why? My code looks like this: using (PowerShell powerShell = PowerShell.Create()) { powerShell.AddScript(scriptText); powerShell.Streams.Progress.DataAdded += ProgressDataAdded; Collection<PSObject> PSOutput = powerShell.Invoke(); }
  • Mathias R. Jessen
    Mathias R. Jessen over 5 years
    @IonutEnache Please ask a new question and include the handler code and what you've tried so far :)