C# Powershell中的.NET事件在结束前未处理
这是一个非常直截了当的问题。我有一个dll,负责读取大量文件。每个文件完成都由事件指示。控制台应用程序会正确处理它,并在参数出现时立即显示信息 另一方面,我想从powershell脚本运行此dll并显示进度条。它没有按预期工作执行结束时会显示进度条,在毫秒内从0%快速上升到100%,并消失。C# Powershell中的.NET事件在结束前未处理,c#,powershell,events,C#,Powershell,Events,这是一个非常直截了当的问题。我有一个dll,负责读取大量文件。每个文件完成都由事件指示。控制台应用程序会正确处理它,并在参数出现时立即显示信息 另一方面,我想从powershell脚本运行此dll并显示进度条。它没有按预期工作执行结束时会显示进度条,在毫秒内从0%快速上升到100%,并消失。 $isVerbose = $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent $finder = New-Object ContentF
$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"
}
它的名字是这样的:geterrorlogs-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"
}
在单线程场景中,实际上不需要使用
Register ObjectEvent
。PowerShell允许您将脚本块转换为委托类型的对象。您可以通过调用事件访问器(add\u EventName
/remove\u 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
变量,以便以后可以将其正确分离。您可以使用此代码段模拟注册ObjectEvent
来添加“本机”事件
使用$args[0]
(等于发送方)和$args[1]
(等于处理程序的事件args类型)来访问值。
例如:
$handler = Register-NativeEvent $MyInstance "MyEventName" { Write-Host $args[1].MyProperty }
并在完成后取消注册:
Unregister-NativeEvent $MyInstance "MyEventName" $handler
GetErrorLogs
是如何工作的?是不是一直堵到手术结束?是否在调用GetErrorLogs
的同一线程中引发FileQueueProgress
?是,它同步运行,同时在同一线程上引发事件。控制台版本与PowerShell版本相比如何?我认为你看到的行为是意料之中的。您在PowerShell中没有异步,因此所有内容都将排队。至少我是这样理解的。注册ObjectEvent…
->$Handler={Write Progress($args[1].Percent])-作为$finder。PSObject。成员。匹配('FileQueueProgress')[0]。价值EventHandlerType$寻找者。添加_FileQueueProgress($Handler)
<代码>注销事件…->$finder。删除_FileQueueProgress($Handler)
,这就是@PetSerAl解决我问题的绝妙答案。谢谢:)!
Unregister-NativeEvent $MyInstance "MyEventName" $handler