Question

Trying to asynchronously call a powershell script within an ASP.NET IHttHandler, I stumbled accross the example on http://msdn.microsoft.com/en-us/library/ee706580(v=vs.85).aspx. My own code looks like this:

using (PowerShell powershell = PowerShell.Create()) {
    powershell.AddScript("1..10 | foreach {$_ ; start-sleep -milli 500}");

    PSDataCollection<PSObject> output = new PSDataCollection<PSObject>();

    output.DataAdded += delegate(object sender, DataAddedEventArgs e) {
        PSDataCollection<PSObject> myp = (PSDataCollection<PSObject>)sender;
        Collection<PSObject> results = myp.ReadAll();
    };

    powershell.InvocationStateChanged += delegate(object sender, PSInvocationStateChangedEventArgs e) {
        if (e.InvocationStateInfo.State == PSInvocationState.Completed) {
            // Clean up
        }
    };

    IAsyncResult asyncResult = powershell.BeginInvoke<PSObject, PSObject>(null, output);
}

Unfortunately, the powershell script is obviously not being executed. No powershell process shows up in the task manager.

I set break points withing the DataAdded and IncovationStateChanged handlers. The first one never gets called, the second one shows, that e.InvocationStateInfo.State never becomes Completed but ends with Stopped.

What am I doing wrong?

Was it helpful?

Solution

This works in a console app:

using (PowerShell powershell = PowerShell.Create())
{
    powershell.AddScript("1..10 | foreach {$_ ; start-sleep -milli 500}");

    var output = new PSDataCollection<PSObject>();

    output.DataAdded += delegate(object sender, DataAddedEventArgs e)
    {
        Console.WriteLine(output[e.Index]);
        var myp = (PSDataCollection<PSObject>)sender;
        Collection<PSObject> results = myp.ReadAll();
    };

    powershell.InvocationStateChanged += delegate(object sender, PSInvocationStateChangedEventArgs e)
    {
        if (e.InvocationStateInfo.State == PSInvocationState.Completed)
        {
            // Clean up
        }
    };

    IAsyncResult asyncResult = powershell.BeginInvoke<PSObject, PSObject>(null, output);

    asyncResult.AsyncWaitHandle.WaitOne();
}

If you don't somehow synchronize or comeback later and wait for the invoke to finish, the PowerShell engine shuts down because powershell.Dispose() gets called as it falls out of your using {} scope.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top