Powershell中的.NET事件直到最后才处理

时间:2017-02-03 15:53:20

标签: c# powershell events

这是一个非常直截了当的问题。我有一个dll负责阅读大量的文件。每个文件完成都由事件指示。控制台应用程序一旦出现就会正确地显示来自args的信息。

另一方面,我想从powershell脚本运行此dll并显示进度条。它没有按预期工作。 执行结束时显示进度条,在0到100%的范围内快速上升,并且消失。

$isVerbose = $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent

$finder = New-Object ContentFinder.LogFinder

if($isVerbose)
{
    Register-ObjectEvent -InputObject $finder -EventName "FileQueueProgress" -Action {Write-Progress ($EventArgs.Percent)} -SourceIdentifier "FileReadingProgressIndicator" | Out-Null
}

try
{
    $path = GetPath
    $date = GetDate

    return $finder.GetErrorLogs($path, $date)
}
catch
{
    Write-Host ($_.Exception.Message)
}
finally
{
    if($isVerbose)
    {
        Unregister-Event -SourceIdentifier "FileReadingProgressIndicator"
    }

    Write-Host "Done"
}  

它的名字如下:Get-ErrorLogs -Verbose。通常我将它分配给变量只是为了能够过滤结果和所有有效的。 我可以采取哪些措施让PS在事件发生的同一时刻对事件做出回应吗?

来自评论的

编辑:答案 这与预期一样有效。报告执行期间的进度,而不是脚本的结尾。

if($isVerbose)
{
    $Handler = {Write-Progress ($args[1].Percent)} -as $finder. PSObject. Members. Match('FileQueueProgress')[0]. Value. EventHandlerType; 
    $finder. add_FileQueueProgress($Handler); 
    #Register-ObjectEvent -InputObject $finder -EventName "FileQueueProgress" -Action {Write-Progress ($EventArgs.Percent)} -SourceIdentifier "FileReadingProgressIndicator" | Out-Null
}

try
{
    $path = GetPath
    $date = GetDate

    return $finder.GetErrorLogs($path, $date)
}
catch{
    Write-Host ($_.Exception.Message)
}
finally
{
    if($isVerbose)
    {
        #Unregister-Event -SourceIdentifier "FileReadingProgressIndicator"
        $finder. remove_FileQueueProgress($Handler)
    }

    Write-Host "Done"
} 

2 个答案:

答案 0 :(得分:1)

在单线程场景中,您实际上不需要使用Register-ObjectEvent。 PowerShell允许您将脚本块转换为委托类型对象。您可以通过直接调用事件访问器(add_EventName / remove_EventName)来附加/分离该代表与事件。

$finder = New-Object ContentFinder.LogFinder

if($isVerbose)
{
    $Handler = {Write-Progress ($args[1].Percent)} -as $finder.PSObject.Members.Match('FileQueueProgress')[0].Value.EventHandlerType
    $finder.add_FileQueueProgress($Handler)
}

try
{
    $path = GetPath
    $date = GetDate

    return $finder.GetErrorLogs($path, $date)
}
catch
{
    Write-Host ($_.Exception.Message)
}
finally
{
    if($isVerbose)
    {
        $finder.remove_FileQueueProgress($Handler)
    }

    Write-Host "Done"
}

注意:我将委托对象保存到$Handler变量,因此我可以稍后将其正确分离。

答案 1 :(得分:1)

您可以使用此代码段模拟Register-ObjectEvent来添加“原生”事件。

function Register-NativeEvent {
    param($Instance, $EventName, [ScriptBlock] $ScriptBlock)

    $handler = $ScriptBlock -as $instance.PSObject.Members.Match($EventName)[0].Value.EventHandlerType
    $handlerMethod = "add_$EventName"
    $instance.$handlerMethod($handler)

    return $handler
}

function Unregister-NativeEvent {
    param($Instance, $EventName, $handler)

    $handlerMethod = "remove_$EventName"
    $instance.$handlerMethod($handler)
}

使用$args[0](等于发送者)和$args[1](等于处理程序的事件args类型)来访问值。 例如:

$handler = Register-NativeEvent $MyInstance "MyEventName" { Write-Host $args[1].MyProperty }

完成后取消注册:

Unregister-NativeEvent $MyInstance "MyEventName" $handler