简体   繁体   中英

Powershell/C# Streams.Progress.DataAdded EventHandler in C# not working as expected

Below an example of the issue I'm running in. This simple script will count to 5 and will trigger the Progress DataAdded event when the progress records are added to the data collection.

void Button_Click(object sender, RoutedEventArgs e)
{
PowerShell ps1 = PowerShell.Create();
ps1.Streams.Progress.DataAdded += new EventHandler<DataAddedEventArgs>(Progress_DataAdded); // Set the event handler when data is added to the progress collection
ps1.AddScript("for($i = 1 ; $i -le 5 ; $i++) {Write-Progress -Activity Count -status $i ; sleep 1}"); // Simple script that will count to 5 and generate the progress activity
ps1.BeginInvoke();
}

void Progress_DataAdded(object sender, DataAddedEventArgs e)
{
listBox1.Items.Add(((PSDataCollection<ProgressRecord>)sender)[e.Index].ToString()); // Add the progress records to a listbox on the UI, this doesn't work
// MessageBox.Show(((PSDataCollection<ProgressRecord>)sender)[e.Index].ToString()); // Display the progress records in a messagebox, this does work
}

When MessageBox is enabled and Listbox disabled it works and it displays the progress records in a messagebox. When MessageBox is disabled and Listbox enabled (as above) it doesn't work, the records are not shown in the listbox. Maybe something to do with the current thread it runs in or by the way the powershell script is invoked. Hopefully someone can get me on the right track with this one, all I want is to display the progress records in a listbox on the UI when the script is executed. Thanks in advance!

This example seems to work fine for me. It prints the appropriate text to the Output window in Visual Studio Express 2013 for Windows Desktop. I am fairly certain that the root cause of the issue you're seeing is that you're calling BeginInvoke() instead of Invoke() . When I tested my sample code below with BeginInvoke() , it did not print the five (5) additional lines to the Debug output. Only the Progress.Add() method successfully caused the event handler to be called.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Management.Automation;
using System.Diagnostics;

namespace PowerShellTest01
{
    class Program
    {
        static void Main(string[] args)
        {
            // 1. Create PowerShell instance
            var ps = PowerShell.Create();
            // 2. Add C# anonymous method to respond to event
            ps.Streams.Progress.DataAdded += delegate(object sender, DataAddedEventArgs e) { Debug.WriteLine("Data was added to progress stream"); };
            // 3. Add a new ProgressRecord instance
            ps.Streams.Progress.Add(new ProgressRecord(5, "test", "test"));
            // 4. Add a PowerShell script that calls Write-Progress
            ps.AddScript("1..5 | % { Write-Progress -Activity 'My Important Activity' -PercentComplete ($PSItem*20) -Status 'This is my status'; Start-Sleep -Milliseconds 200; }");
            // 5. Invoke the script synchronously
            ps.Invoke();
            // 6. Wait for user input
            Console.Read();
        }
    }
}

Update : Including code that demonstrates adding the object to a ListBox .

void Progress_DataAdded(object sender, DataAddedEventArgs e)
{
    Debug.WriteLine("sender type is: " + sender.GetType());
    var records = (PSDataCollection<ProgressRecord>)sender;
    Debug.WriteLine("Progress stream contains {0} records", records.Count);
    ListProgressRecords.Items.Add(records[e.Index]);
}

PowerShell:ProgressRecords

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM