# encoding: ascii
# api: powershell
# title: AsyncCallbacks in .NET
# description: Allows running ScriptBlocks via .NET async callbacks. Internally this is managed by converting .NET async callbacks into .NET events. This enables PowerShell 2.0 to run ScriptBlocks indirectly through Register-ObjectEvent.
# version: 0.1
# type: function
# author: Oisin Grehan
# license: CC0
# function: New-ScriptBlockCallback
# x-poshcode-id: 1382
# x-archived: 2016-04-04T21:45:29
# x-published: 2010-10-09T13:32:00
#
#
#requires -version 2.0
function New-ScriptBlockCallback {
param(
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[scriptblock]$Callback
)
<#
.SYNOPSIS
Allows running ScriptBlocks via .NET async callbacks.
.DESCRIPTION
Allows running ScriptBlocks via .NET async callbacks. Internally this is
managed by converting .NET async callbacks into .NET events. This enables
PowerShell 2.0 to run ScriptBlocks indirectly through Register-ObjectEvent.
.PARAMETER Callback
Specify a ScriptBlock to be executed in response to the callback.
Because the ScriptBlock is executed by the eventing subsystem, it only has
access to global scope. Any additional arguments to this function will be
passed as event MessageData.
.EXAMPLE
You wish to run a scriptblock in reponse to a callback. Here is the .NET
method signature:
void Bar(AsyncCallback handler, int blah)
ps> [foo]::bar((New-ScriptBlockCallback { ... }), 42)
.OUTPUTS
A System.AsyncCallback delegate.
#>
# is this type already defined?
if (-not ("CallbackEventBridge" -as [type])) {
Add-Type @"
using System;
public sealed class CallbackEventBridge
{
public event AsyncCallback CallbackComplete = delegate { };
private CallbackEventBridge() {}
private void CallbackInternal(IAsyncResult result)
{
CallbackComplete(result);
}
public AsyncCallback Callback
{
get { return new AsyncCallback(CallbackInternal); }
}
public static CallbackEventBridge Create()
{
return new CallbackEventBridge();
}
}
"@
}
$bridge = [callbackeventbridge]::create()
Register-ObjectEvent -input $bridge -EventName callbackcomplete -action $callback -messagedata $args > $null
$bridge.callback
}